寄生式组合继承的核心目标是让子类正确继承父类实例属性且复用原型方法,同时修复constructor指向;它通过Object.create创建干净原型副本、手动修正constructor、赋值原型三步实现,避免传统组合继承的双重调用及引用类型共享问题。

寄生式组合继承的核心目标,是让子类既能正确继承父类的实例属性(避免共享引用类型),又能复用父类原型上的方法(不重复创建父类实例),同时修复因重写原型导致的 constructor 指向丢失问题。它比传统组合继承少一次父类构造函数调用,真正实现“只调用一次”。
为什么传统组合继承会双重调用?
传统组合继承写法是:
- 在子类构造函数内用
SuperType.call(this, ...)调用一次父类构造函数(初始化实例属性) - 又用
SubType.prototype = new SuperType()创建父类实例来赋值原型(导致第二次调用)
这不仅浪费性能,更关键的是:第二次调用时,父类中定义的引用类型属性(如数组、对象)会被所有子类实例共享——比如 this.color = ['red'],一个实例 push 后,其他实例也会看到变化。
寄生式组合继承的关键三步
它不直接用 new SuperType() 赋原型,而是用更轻量的方式“寄生”出一个干净的原型副本:
-
用
Object.create(SuperType.prototype)创建空对象,该对象的__proto__指向父类原型,但不执行父类构造函数 -
手动修正
constructor:因为Object.create创建的对象没有constructor属性,需显式设为SubType -
将该对象赋给
SubType.prototype,完成原型链挂载
这样,子类实例属性由 call 独立初始化,原型方法由共享的干净副本提供,无冗余调用,也无引用污染。
代码结构对比更清晰
传统组合继承原型赋值写法:
SubType.prototype = new SuperType(); // ❌ 触发第二次构造函数执行
寄生式写法:
function inheritPrototype(SubType, SuperType) {<br> const prototype = Object.create(SuperType.prototype);<br> prototype.constructor = SubType;<br> SubType.prototype = prototype;<br>}
调用时只需 inheritPrototype(SubType, SuperType),后续所有子类实例都拥有独立属性 + 共享方法,且 instanceof 和 isPrototypeOf 判断完全正常。
实际效果验证点
测试两个实例的引用属性是否隔离:
- 实例1 修改
color.push('blue')→ 只影响自己 - 实例2 的
color仍是原始值,未被污染 - 调用
sayName()等原型方法仍能正常工作 - 打印
SubType.prototype.constructor === SubType返回true(修复成功)
这套模式在 ES5 环境下是组合继承的最优解,语义清晰、行为可靠、无副作用。

















