寄生组合式继承

1,177 阅读2分钟

寄生式组合继承通过盗用构造函数继承属性,但使用混合式原型链继承方法。基本思路是不通过调 用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。说到底就是使用寄生式继承来继承父 类原型,然后将返回的新对象赋值给子类原型。寄生式组合继承的基本模式如下所示:

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);

Snipaste_2021-05-26_17-19-16.jpg

这里只调用了一次 SuperType 构造函数,避免了 SubType.prototype 上不必要也用不到的属性,因此可以说这个例子的效率更高。而且,原型链仍然保持不变,因此 instanceof 操作符和isPrototypeOf() 方法正常有效。寄生式组合继承可以算是引用类型继承的最佳模式。