寄生组合式继承是目前最理想的继承方式,它复用父类构造函数、保持原型链正确性、仅调用一次父类构造函数;ES6的class extends是其语法糖优化实现。

寄生组合式继承是目前最理想的继承方式,它既复用了父类构造函数(避免原型链共享问题),又让子类原型真正指向父类原型(保持 instanceof 和 constructor 正确性),同时不调用两次父类构造函数。
核心思路:用空函数桥接原型,切断 new Parent() 的副作用
关键在于——不能直接 Child.prototype = new Parent()(会执行父类构造逻辑、污染原型),也不能用 Object.create(Parent.prototype)(虽避免执行构造函数,但若父类原型上有引用类型属性,仍可能被共享)。真正的解法是:
- 创建一个中间空函数,仅用于“中转”原型链关系
- 将该空函数的 prototype 设为 Parent.prototype
- 再用 new 这个空函数 实例化出干净的原型对象
- 把 Child.prototype 指向这个干净对象,并修正 constructor
标准实现(ES5 兼容写法)
下面这段代码就是公认的“完美”寄生组合式继承封装:
function inheritPrototype(Child, Parent) {const F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
使用时分两步:
立即学习“Java免费学习笔记(深入)”;
- 先在子类构造函数里调用
Parent.call(this, ...args)—— 继承实例属性 - 再在构造函数定义后调用
inheritPrototype(Child, Parent)—— 继承原型方法
为什么比其他方式更“完美”?
对比常见缺陷:
-
原型链继承:子类原型是
new Parent(),父类构造函数被调用,且所有实例共享引用属性 - 借用构造函数:无法继承原型上的方法,方法无法复用
-
组合继承:父类构造函数被调用两次(一次在
Child.prototype = new Parent(),一次在Parent.call()) - 寄生式继承:只是浅拷贝原型,没解决 constructor 指向和 instanceof 判断问题
寄生组合式继承只调用一次父类构造函数(仅在子类实例化时),原型链干净,constructor 正确,instanceof 可靠,无属性共享风险。
现代替代方案(ES6+ 推荐)
如果环境支持,class + extends 是语法糖,底层正是寄生组合式继承的优化实现:
constructor(name) { this.name = name; }
say() { return `Hi, ${this.name}`; }
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
}
它自动处理原型链、constructor 修正、super 调用,且语义清晰。除非需兼容老旧环境,否则无需手写寄生组合式继承。


















