学习打卡 JavaScript面向对象-继承
JS的继承也肝了 满打满算两三天了,虽然还是有很多地方没有弄懂,还是强行做个整理吧先。
1. 原型链继承
这种方式的继承已经在之前一篇博文 学习打卡 JavaScript面向对象编程-原型链 写的相对详细了,不再赘述,直接上源码:
function Super(name){ this.name = name; this.superValue = `SuperArea ${this.name}`; } Super.prototype.getSuperValue = function(){ return this.superValue; } function Sub(name,age){ this.name = name; this.age = age; this.subValue = `SubArea ${this.name + this.age}`; } Sub.prototype = new Super('xhy'); Sub.prototype.getSubValue = function(){ return this.subValue; } var el = new Sub('yhs', 26); console.log(el.getSuperValue()); // SuperArea xhy
原型链继承最大的问题除了繁琐以外,还在于会改变子类的constructor的指向。当然这也不是大事情,如果真的很需要子类原型对象 构造函数指向正确的话,重新定义一下即可;
原型链继承最大的问题,仍然在于引用类型值的共享化:
function Super(){ this.arr = [1, 2, 3, 4, 5]; } function Sub(){} Sub.prototype = new Super(); var el = new Sub(); el.arr.push(6); console.log(el.arr); //(6) [1, 2, 3, 4, 5, 6] var el2 = new Sub(); console.log(el2.arr); //(6) [1, 2, 3, 4, 5, 6] console.log(Sub.prototype.arr); //(6) [1, 2, 3, 4, 5, 6]
当 Sub 通过原型链继承了 Super 后,sub.prototype 就变成了Super的一个实例,它也拥有了一个它自己的属性 arr ——就和专门创建了一个 Sub.prototype.arr 属性一样;so 当在任一一个Sub的实例上对引用数据类型的值进行修改后,所有的实例,包括子类的原型对象 中的值都会被强制同步
笔者在b站发现了几种奇奇怪怪的 由原型链继承 衍化而来的继承方式,美其名曰…“改良”?
什么 让子类跳过父类本身,直接继承父类的原型对象 以达到提高运行效率的目的…个人感觉没啥意义,既没有从根本上解决原型链继承的不足,还莫名其妙添加了不少的需要解决的bug…有兴趣的小伙伴可以去瞄一眼:B站 继承及原型链。
2. 借用构造函数继承
也被称为 伪造对象 或 经典继承,在子类构造函数内部,通过使用apply() 或 call() 方法执行父类的构造函数,可以很好地解决原型链继承所带来的问题:
function Super(name){ this.name = name; this.arr = [1, 2, 3, 4, 5]; } function Sub(name, age){ Super.call(this,name); this.age = age; } var el = new Sub('xhy', 21); el.arr.push(6); console.log(el.name + " " + el.arr); // xhy 1,2,3,4,5,6 var el2 = new Sub('yhs', 26); console.log(el2.name + " " + el2.arr);// yhs 1,2,3,4,5 */
并且相对于原型链而言,借用构造函数有一个很大的优势:可以在子类构造函数中向父类构造函数传递参数:
function Sub(){ Super.call(this,"pgOne"); this.age = age; } var el = new Sub(); console.log(el.name); // "pgOne"
3. 组合式继承
也称伪经典继承,将原型链与借用构造函数的技术组合到一块,从而扬长避短的一种继承方式;
思路:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承:
function Super(name){ this.name = name; this.arr = [1, 2, 3, 4, 5]; } Super.prototype.greeting = function(){ return `Hi, I'm ${this.name}!`; } function Sub(name,age){ Super.call(this,name); this.age = age; } Sub.prototype = new Super('xhy'); //Sub.prototype.constructor = Sub; Sub.prototype.greetingD = function(){ return `Hi, I'm ${this.name}, I'm ${this.age} years old!` } var el = new Sub("aka", 13); el.arr.push(6); var el2 = new Sub("yhs", 26); console.log(el2.constructor);//Super console.log(el2.arr); // (5) [1, 2, 3, 4, 5] console.log(el2.greeting()); // Hi, I'm yhs!! console.log(el2.greetingD()); // Hi, I'm yhs, I'm 26 years old!
如果进行子类构造函数的重定位后,这种组合式继承基本没有什么大毛病,也是现阶段JS最常用的继承模式。
4. 拷贝继承
function extend(Child, Parent){ var c = Child.prototype; var p = Child.prototype; for(var i in p){ c[i] = p[i]; } }
.我枯了 不禁怀疑自己这几天都学了啥…哪个大佬能告诉我这种土办法有什么缺陷嘛?!(这种方法下 它!连!构造函数的指向!都是正确的!)
5. 原型式继承
.原型式继承 携带着 寄生式继承,笔者了解的不是那么OK,偷篇大佬照搬红宝书的博文,插个眼,过段时间再来瞄一眼就不信还啃不下来~ JS继承 原型式继承 —— weixin_34332905
6. 组合式继承+原型式继承
.笔者也不确定用这种方式来称呼合不合适,如下的继承方式是我无意中发现国外的大佬写的,感觉意外的好用和舒爽:
function Super(name, age, sex){ this.name = name; this.age = age; this.sex = sex; } Super.prototype.greeting = function(){ return `Hi, I'm ${this.sex == '男'? 'Mr':'Miss'} ${this.name}, I'm ${this.age} years old!` } function Sub(name, age, sex, msg){ Super.call(this, name, age, sex); this.msg = msg; } Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; var el = new Sub('xhy', 21, '男', 'nothing'); console.log(el); console.log(el.greeting()); // Hi, I'm Mr xhy, I'm 21 years old!
7. ES6 继承
.es6中提供了OOP类和继承
.直接写class 无需花里胡哨的操作 —— 在原型里挣扎了数十个小时的笔者如沐春风~
class Super{ constructor(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } greeting(){ return `Hi, I'm ${this.sex == '男'? 'Mr':'Miss'} ${this.name}, I'm ${this.age} years old!`; } static show(){ return 'Here is SuperArea!'; } } class Sub extends Super { constructor(name, age, sex, msg){ super(name, age, sex); this.msg = msg; } } var el = new Sub('xhy', 21, '男', 'nothing'); console.log(el); console.log(el.greeting()); // Hi, I'm Mr xhy, I'm 21 years old! */
有class ,有extends, 有super() ,甚至还有static…
轻轻松松完成继承~ 啊这也太爽了吧~ 我不想搞前端了我想弄java去了(笑)
————————————————————————————————— END ————————————————————
- 轻松学习JavaScript十三:JavaScript基于面向对象之继承(包含面向对象继承机制)
- html5学习笔记---05.JavaScript 中的面向对象,继承和封装
- JavaScript学习笔记6 面向对象之继承
- 学习javascript面向对象 javascript实现继承的方式
- 学习javascript面向对象 javascript实现继承的方式
- Atlas学习手记(28):JavaScript面向对象的扩展(二):继承Inheritance
- 前端学习之JavaScript面向对象(2)——继承
- 从面试题学习Javascript——面向对象(继承)
- 韩顺平 javascript教学视频_学习笔记19_js面向对象三大特征(封装,继承,多态)
- javascript面向对象学习笔记(三)——继承
- html5学习笔记---05.JavaScript 中的面向对象,继承和封装
- js设计模式学习之面向对象的javascript(三)--原型式继承
- javascript面向对象学习笔记(一)——继承
- Atlas学习手记(28):JavaScript面向对象的扩展(二):继承Inheritance
- javascript面向对象学习笔记(一)——继承
- PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)
- javascript继承学习系列之四:组合继承(Combination Inheritance)
- Javascript学习笔记九——prototype封装继承
- 黑马程序员——java基础学习(面向对象,继承)
- 面向对象的javascript系列文章(3)继承——代码重用