寄生组合式继承通过仅调用一次父类构造函数解决重复调用问题:先用空函数桥接父类原型以避免new Parent()的副作用,再在子类构造函数中调用Parent.call(this)初始化实例属性。

寄生组合式继承通过“只调用一次父类构造函数”来彻底避开父类重复调用问题,核心在于:不直接用 Parent.call(this) 在子类构造函数中初始化父类实例属性,也不用 new Parent() 设置子类原型,而是用一个空函数桥接并复用父类原型——这样既继承了父类原型方法,又避免了执行父类构造逻辑两次。
为什么传统组合继承会重复调用父类构造函数
传统组合继承写法:
function Child(name) {
Parent.call(this, name); // 第一次调用 Parent 构造函数
}
Child.prototype = new Parent(); // 第二次调用 Parent 构造函数(为设置原型)
这里 new Parent() 会执行父类构造函数,可能引发副作用(如发请求、修改全局状态、重复初始化对象属性),且在 Child.prototype 上挂载的实例属性(如 this.name = name)会被所有子类实例共享,造成数据污染。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
寄生组合式继承的关键三步
-
创建干净的原型代理:定义一个空函数
F,将其prototype指向Parent.prototype,再用new F()得到一个无副作用的原型对象; -
正确设置子类原型:把
Child.prototype赋值为这个干净对象,并修正constructor指回Child; -
仅在子类构造中调用一次父类构造:在
Child构造函数内执行Parent.call(this, ...),确保实例属性独立、初始化可控。
标准实现代码(ES5)
function inheritPrototype(Child, Parent) {
const F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
function Parent(name) {
this.name = name;
console.log('Parent constructor called'); // 只应输出一次 per instance
}
function Child(name, age) {
Parent.call(this, name); // ✅ 唯一一次父类构造调用
this.age = age;
}
inheritPrototype(Child, Parent);
const c1 = new Child('Alice', 25); // 输出一次 'Parent constructor called'
const c2 = new Child('Bob', 30); // 再输出一次 —— 各自独立,无共享
ES6 class 的等效行为(自动规避该问题)
class 语法底层已采用类似寄生组合式的设计逻辑:super() 是唯一触发父类构造函数的时机,且 Child.prototype 继承自 Parent.prototype(通过 Object.setPrototypeOf),不会执行 new Parent()。所以只要不手动写 Child.prototype = new Parent(),就天然避开重复调用。
立即学习“Java免费学习笔记(深入)”;

















