所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
组合继承弥补了原型链和盗用构造函数的不足,是js中使用最多的继承模式。
- 实现思路: 不必为了指定子类型的原型而调用父类的构造函数,我们所需要的无非就是父类原型的一个副本而已。
- 本质上,就是使用寄生式继承来继承父类的原型,然后再将结果指定给子类的原型。 寄生组合式继承的基本模式如下代码:
function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); //创建对象 prototype.constructor = subType; //增强对象 subType.prototype = prototype; //指定对象 }
上述示例代码中,函数接收两个参数:子类构造函数和父类构造函数。在函数内部,第一步是创建父类原型的一个副本。第二步是为创建的副本添加 constructor 属性,从而弥补因重写原型而失去的默认的constructor 属性。最后一步,将新创建的对象(即副本)赋值给子类型的原型。
function inheritPrototype(subType, superType){ var prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本 prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性 subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型 } // 父类初始化实例属性和原型属性 function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; // 借用构造函数传递增强子类实例属性(支持传参和避免篡改) function SubType(name, age){ SuperType.call(this, name); this.age = age; } // 将父类原型指向子类 inheritPrototype(SubType, SuperType); // 新增子类原型属性 SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType("jack", 23); var instance2 = new SubType("rose", 20); instance1.colors.push("2"); // ["red", "blue", "green", "2"] instance1.colors.push("3"); // ["red", "blue", "green", "3"]
上述代码的高效率体现在它只调用了一次 SuperType 构造函数,并且因此避免了在 SubType. prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf()。