寄生式组合继承通过盗用构造函数继承属性,但使用混合式原型链继承方法。基本思路是不通过调 用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。说到底就是使用寄生式继承来继承父 类原型,然后将返回的新对象赋值给子类原型。寄生式组合继承的基本模式如下所示:
function inheritPrototype(subType, superType) {
let prototype = object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 赋值对象
}
这个 inheritPrototype() 函数实现了寄生式组合继承的核心逻辑。这个函数接收两个参数:子
类构造函数和父类构造函数。在这个函数内部,第一步是创建父类原型的一个副本。然后,给返回的
prototype 对象设置 constructor 属性,解决由于重写原型导致默认 constructor 丢失的问题。最后将新创建的对象赋值给子类型的原型。如下例所示,调用 inheritPrototype() 就可以实现前面例子中的子类型原型赋值
寄生组合式继承实现:
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性
subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
}
// 父类初始化实例属性和原型属性
function superType(name) {
this.name = name;
this.colors = [1, 2, 3, 4, 5];
}
superType.prototype.saySuper = function () {
console.log("super");
};
// 借用构造函数传递增强子类实例属性(支持传参和避免篡改)
function subType(name, age) {
superType.call(this, name);
this.age = age;
}
subType.prototype.saySub = function () {
console.log("sub");
};
// 将父类原型指向子类
inheritPrototype(subType, superType);
let instance1 = new subType("zs", 10);
instance1.colors.push(10);
let instance2 = new subType("ls", 20);
instance2.colors.push(100);
console.log(instance1);
console.log(instance2);
这里只调用了一次 SuperType 构造函数,避免了 SubType.prototype 上不必要也用不到的属性,因此可以说这个例子的效率更高。而且,原型链仍然保持不变,因此 instanceof 操作符和isPrototypeOf() 方法正常有效。寄生式组合继承可以算是引用类型继承的最佳模式。