构造函数继承的核心目的是避免原型链上引用类型属性被所有实例共享;它通过在子类构造函数中用call/apply调用父类构造函数,使每个子类实例拥有独立属性副本,支持传参,但不继承父类原型方法。

构造函数继承(也叫借用构造函数或 constructor stealing)的核心目的,就是避开原型链上引用类型属性被所有实例共享的问题。
为什么需要它?
原型链继承时,子类原型是父类的一个实例。如果父类构造函数里定义了数组、对象这类引用类型属性(比如 this.hobbies = ['reading']),那所有子类实例都会指向同一个数组——改一个,全跟着变。这通常不是我们想要的。
它是怎么工作的?
在子类构造函数内部,用 call() 或 apply() 显式调用父类构造函数,并把 this 绑定到当前正在创建的子类实例上。这样,父类构造函数里的初始化逻辑(包括给 this 赋值)就直接作用于子类实例本身。
- 每个子类实例都拥有自己独立的一份属性副本,互不影响
- 支持向父类传参,比如 Parent.call(this, name, level)
- 可以模拟多继承,连续调用多个父类构造函数
但它不继承原型方法
注意:这种方式只复制了构造函数内定义的属性和方法(即写在 this.xxx = ... 上的),而父类原型上定义的方法(如 Parent.prototype.sayName = function() {...})不会被继承。
- 子类实例无法访问父类原型上的方法
- instanceof 判定会失败(child instanceof Parent 返回 false)
- 每个实例都重新创建构造函数内的函数(如 this.eat = function(){...}),造成内存冗余
典型适用场景
适合需要隔离数据状态、避免意外共享的场合,比如:
- 创建多个配置对象,每个都要有自己独立的 options 对象或 handlers 数组
- 构建工具类或插件实例,要求属性完全私有、不可被其他实例干扰
- 作为组合继承中“继承实例属性”的那一半,配合原型链补足方法复用











