借用构造函数能彻底避免引用类型属性共享,因每次创建子类实例时均通过call/apply调用父类构造函数,使this指向当前实例,从而为每个实例独立初始化属性(如this.colors = ['red']),而非挂载于原型上被共用。

借用构造函数能直接让每个子类实例拥有自己的一份属性,尤其是引用类型(比如数组、对象),彻底避免多个实例互相影响。
为什么需要解决属性共享问题
原型链继承时,如果父类在构造函数外把引用类型挂到 prototype 上,所有实例会共用同一份数据。例如一个 colors 数组被修改,其他实例立刻“感知”到——这不是预期行为。
- 父类定义
Parent.prototype.colors = ['red']→ 所有子类实例共享这个数组 - 一个实例执行
c1.colors.push('blue')→c2.colors也变成['red', 'blue']
借用构造函数怎么保证属性独立
核心是:每次创建子类实例时,都调用一次父类构造函数,并把 this 绑定到当前子类实例上。这样父类内部的 this.xxx = xxx 就直接写进该实例自身,而不是原型。
- 用
Parent.call(this, ...args)或Parent.apply(this, args) - 父类中定义的
this.colors = ['red']、this.name = name全部成为实例自有属性 - 每个
new Child()都会重新执行一遍初始化逻辑,生成独立副本
实际写法与关键细节
子类构造函数里调用父类,同时传参初始化;不改动原型链,也不依赖 new Parent()。
- ✅ 正确:
function Child(name) { Parent.call(this, name); this.type = 'child'; } - ❌ 错误:
Child.prototype = new Parent()—— 这是原型链方式,会导致共享 - ⚠️ 注意:只继承实例属性,
Parent.prototype上的方法不会自动可用
它不是万能方案,但定位清晰
借用构造函数专注解决“属性隔离”,尤其适合需要状态完全独立的场景,比如配置对象、表单模型、工具类混入等。若还需复用方法或支持 instanceof 判断,应配合原型链使用,形成寄生组合继承。










