javascript构造函数继承的核心是寄生组合式继承,即用parent.call(this)实现实例属性独立,再用object.create(parent.prototype)继承原型方法并修复constructor。

JavaScript 的构造函数继承,核心是让子构造函数能访问父构造函数的实例属性(即通过 this 绑定的属性),同时避免共享引用类型属性。最常用且推荐的方式是使用 寄生组合式继承,它结合了原型链继承(复用方法)和构造函数继承(保障实例属性独立)的优点。
1. 构造函数继承(借用父类构造函数)
在子构造函数内部调用父构造函数,并绑定 this,从而让每个实例拥有自己的一份属性(尤其是引用类型):
function Parent(name) {
this.name = name;
this.hobbies = ['reading'];
}
function Child(name, age) {
// 关键:借用父构造函数,为当前实例初始化属性
Parent.call(this, name); // 不用 new Parent(),避免多余实例和副作用
this.age = age;
}
const c1 = new Child('Alice', 25);
const c2 = new Child('Bob', 30);
c1.hobbies.push('coding');
console.log(c2.hobbies); // ['reading'] —— 独立副本,没被影响
2. 原型方法继承(复用父类方法)
只靠 Parent.call() 无法继承原型上的方法(如 Parent.prototype.sayHi)。需要把父类原型“挂”到子类原型上,但不能直接赋值(会共享修改),推荐用 Object.create():
Parent.prototype.sayHi = function() {
console.log(`Hi, I'm ${this.name}`);
};
// 正确设置原型链
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 修复 constructor 指向
// 现在子实例可以调用父类原型方法
const c = new Child('Tom', 28);
c.sayHi(); // Hi, I'm Tom
3. 封装成可复用的继承工具函数
手动写 Object.create 和修复 constructor 容易遗漏,可封装一个通用函数:
function inherit(Child, Parent) {
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
}
// 使用
function Animal(name) { this.name = name; }
Animal.prototype.eat = function() { console.log(`${this.name} is eating`); };
function Dog(name, breed) {
Animal.call(this, name); // 继承实例属性
this.breed = breed;
}
inherit(Dog, Animal); // 继承原型方法
const dog = new Dog('Leo', 'Golden Retriever');
dog.eat(); // Leo is eating
4. 注意事项与常见错误
以下写法看似简单,但有严重隐患:
- ❌ Child.prototype = new Parent():会执行父构造函数,可能触发副作用(如发请求、改全局状态),且所有子类实例共享同一份引用属性(如数组、对象)
-
❌ 忘记修复 constructor:导致
instance.constructor === Parent,影响 instanceof 判断和调试 - ❌ 只用 call 不设原型:子实例无法访问父类原型方法,失去代码复用意义
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











