一、回顾 组合继承 (伪经典继承)
-
结合了构造函数继承+对象原型继承
-
不足的地方是:每个实例对象 都执行了两次Super函数,一次是prototype赋值,一次是Super.call
-
并且 我们预期是想继承 父级的原型属性,而Suber.prototype = new Super(); 还另外承了this 对象,
// 组合继承
function Super() {
this.pbrand = 'super';
// 添加引用值
this.a = [1, 2, 3, 4, 5];
}
function Suber() {
this.bbrand = 'suber';
//构造函数继承
Super.call(this);
}
Suber.prototype = new Super(); //对象原型继承
let suber1 = new Suber();
console.log(suber1);
我曾想那把Suber.prototype = new Super(); , 改成Suber.prototype=Super.prototype;,那不是很奈斯?构造函数继承this,Suber.prototype = Super.prototype;继承prototype。后来经实践发现:
function Super() {
this.pbrand = 'super';
// 添加引用值
this.a = [1, 2, 3, 4, 5];
}
Super.prototype.b = ['a','b'];
function Suber() {
this.bbrand = 'suber';
//构造函数继承
Super.call(this);
}
Suber.prototype = Super.prototype;
Suber.prototype.str = 'suber';
let suber1 = new Suber();
console.log(suber1);
结果发现,Suber 与 Super的实例中原型值一样。因为 prototype 也是引用值,经过 Suber.prototype = Super.prototype,两者指向同一块内容。
那有没有完美解决伪经典继承缺陷的方法呢?有,那就是接下来的寄生式组合继承。
二、寄生式组合继承
听名字猜它结合了哪些继承方式:寄生式,组合(构造)。
// 经典继承 寄生式组合继承
// 寄生式的核心:工厂函数
function inheritPrototype(sub,sup){
// Object.create是ES5才有的,为了兼容可以自己写一个函数
// 只继承了prototype
let prototype = Object.create(sup.prototype);
sub.prototype = prototype;
// 增强对象:标明构造函数
prototype.constructor = sub;
}
// 父级
function Super(){
this.brand = 'super';
this.a = ['a','b'];
}
Super.prototype.say = function(){
console.log('i`m ',this.brand);
}
// 子级
function Suber (){
this.brand = 'suber';
this.a = [1,2,3,4];
Super.call(this);
}
//调用工厂函数实现继承
inheritPrototype(Suber,Super);
let suber1 = new Suber();
let super1 = new Super();
// 修改一下子级的原型
Suber.prototype.str = 'suber';
console.log(suber1);
console.log(super1);
结果可以看出:
- 子级的原型更改,不会影响到父级的原型,
- 父级的原型,子级也能继承
- 父级的this 对象,子级也能继承
- 所以这是经典继承!
要说还有没有别的继承:es6 新引入的class了解一下…