寄生组合式继承通过Object.create(Parent.prototype)复用父类原型,避免new Parent()导致的父构造函数二次调用及引用属性共享问题,仅在Parent.call(this)时执行一次父构造函数。

组合继承本身并不能解决父类构造函数被调用两次的问题,它恰恰是这个问题的源头。真正用来解决它的,是寄生组合式继承——它是对组合继承的优化,核心目标就是只调用一次父类构造函数。
为什么组合继承会调用父类构造函数两次?
问题出在两处执行逻辑上:
- 子类构造函数内部调用
Parent.call(this, ...):这是第一次,用于给当前实例初始化属性(比如this.name、this.colors) - 设置原型链时写
Child.prototype = new Parent():这是第二次,为了继承父类原型上的方法(如sayName),但new Parent()必然触发父类构造函数执行,且此时无法传参,还会把本该属于实例的属性(如colors = ['red', 'blue'])错误地挂到原型上,造成所有子实例共享同一份引用数据
寄生组合式继承怎么只调用一次?
关键在于不通过 new Parent() 去创建原型对象,而是直接复用父类的原型对象本身:
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
- 用
Object.create(Parent.prototype)创建一个空对象,它的__proto__指向Parent.prototype,因此能访问所有父类原型方法 - 这个过程完全不执行
Parent构造函数,避免了第二次调用和冗余属性 - 再手动把
constructor指回子类,保持语义正确:Child.prototype.constructor = Child
标准写法示例
封装一个复用函数更清晰:
立即学习“Java免费学习笔记(深入)”;
function inherit(Child, Parent) {
const proto = Object.create(Parent.prototype);
proto.constructor = Child;
Child.prototype = proto;
}
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name); // ✅ 只在这里调用一次
this.age = age;
}
inherit(Child, Parent); // ✅ 不 new Parent,只复用原型
对比效果
优化后:
- 父类构造函数仅在
Parent.call(this, ...)时执行一次,参数可控,实例属性独立 - 原型链干净:
Child.prototype上没有冗余的name或colors,只有方法和正确的constructor - 引用类型属性(如
colors)不会被多个子实例意外共享

















