Skip to main content

组合式继承

3.组合继承:使用原型链实现对原型方法的继承,借用构造函数来实现对实例属性的继承。

实际上不管代码怎么变,继承都基于两种方式:

1.通过原型链,即子类的原型指向父类的实例从而实现原型共享。 2.借用构造函数,即通过js的apply、call实现子类调用父类的属性、方法;

A.原型链方式可以实现所有属性方法共享,但无法做到属性、方法独享例

如Sub1修改了父类的函数,其他所有的子类Sub2、Sub3...想调用旧的函数就无法实现了)

B.而借用构造函数除了能独享属性、方法外还能在子类构造函数中传递参数,但代码无法复用。

总体而言就是可以实现所有属性方法独享,但无法做到属性、方法
共享(例如,Sub1新增了一个函数,然后想让Sub2、Sub3...都可以用的话就无法实现了,只能Sub2、Sub3...各自在构造函数中新增)

组合继承就是把以上两种继承方式一起使用,把共享的属性、方法用原型链继承实现,独享的属性、方法用借用构造函数实现,所以组合继承几乎完美实现了js的继承; 组合继承有一个小bug,实现的时候调用了两次超类(父类); 性能上不合格啊有木有!怎么解决呢?于是“寄生继承”就出来了

  • 实现: 使用原型链实现对原型方法的继承,借用构造函数来实现对实例属性的继承。 缺点在子类实力化的过程中父类函数执行了2次 缺点 Dog Animal指向了同一块统建,当改变其中任意一个值另外一个也改变

特点: 弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法 既是子类的实例,也是父类的实例 不存在引用属性共享问题 可传参 函数可复用 缺点: 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

function hasPrototypeProperty(object, name) {
return !object.hasOwnProperty(name) && name in object;
}
// 父类
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function () {
console.log(this.name);
};

// 子类
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}

// 1.使用原型链实现对原型方法的继承
SubType.prototype = new SuperType("hehe");

SubType.prototype.sayAge = function () {
console.log(this.age);
};

// 2.借用构造函数来实现对实例属性的继承
const instance1 = new SubType("Nicholas", 29);

instance1.colors.push("black");
console.log("组合继承例子2:", instance1.colors); //"red,blue,green,black"

instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29

const instance2 = new SubType("Greg", 27);
console.log("组合继承例子2:", instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27

//delete instance1.name;
console.log("组合继承例子2", hasPrototypeProperty(instance1, "colors"));
console.log("组合继承例子2:", hasPrototypeProperty(instance1, "name"));

//5.组合继承
//5.组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
/*
function Cat_5(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat_5.prototype = new Animal();
// 感谢 @学无止境c 的提醒,组合继承也是需要修复构造函数指向的。
Cat_5.prototype.constructor = Cat_5;

var cat_5 = new Cat_5();
console.log("E-1:",cat_5.name);
console.log("E-2:",cat_5.sleep());
console.log("E-3:",cat_5 instanceof Animal); // true
console.log("E-4:",cat_5 instanceof Cat_5); // true
*/