原型继承通过设置子类prototype指向父类原型(如Object.create(Animal.prototype))实现方法复用,需修复constructor;避免直接new Parent()以防副作用和引用属性共享;ES6 class底层仍基于此机制。

在 JavaScript 中,传统的原型继承是通过手动设置构造函数的 prototype 属性指向另一个构造函数的实例来实现的,核心是让子类的原型链“链接”到父类的原型,从而复用父类的方法和属性。
1. 基本步骤:设置子类原型为父类实例
这是最经典的做法,也称为「寄生组合式继承」前的朴素实现(注意:直接赋值 Child.prototype = new Parent() 有缺陷,需配合修正):
- 定义父构造函数,并在其
prototype上添加共享方法 - 定义子构造函数,在其内部调用
Parent.call(this, ...)实现属性继承(借用构造函数) - 让
Child.prototype指向new Parent()的实例,建立原型链 - 修复
constructor指针,避免子类实例的constructor指向父类
示例:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a sound');
};
function Dog(name, breed) {
Animal.call(this, name); // 继承实例属性
this.breed = breed;
}
// 关键:建立原型链
Dog.prototype = Object.create(Animal.prototype);
// 修复 constructor
Dog.prototype.constructor = Dog;
Dog.prototype.speak = function() {
console.log(this.name + ' barks');
};
2. 为什么不用 new Parent() 直接赋值?
直接写 Dog.prototype = new Animal() 会导致两个问题:
- 如果
Animal构造函数有副作用(如发请求、修改全局状态),会在继承时意外执行 - 所有
Dog实例会共享父类实例上的**引用类型属性**(比如this.hobbies = []),造成数据污染
Object.create(Animal.prototype) 只创建一个干净空对象,其 [[Prototype]] 指向 Animal.prototype,不执行构造函数,更安全。
3. 确保正确调用父类方法
子类方法中若需调用父类同名方法,应显式使用 Animal.prototype.methodName.call(this, ...):
Dog.prototype.speak = function() {
Animal.prototype.speak.call(this); // 先执行父类逻辑
console.log(this.name + ' barks loudly');
};
4. ES6 class 是语法糖,底层仍是原型链
class extends 和 super() 在编译后依然基于上述原型操作:
-
extends Parent内部等价于Child.prototype = Object.create(Parent.prototype) -
super()等价于Parent.call(this, ...) - 静态方法通过
Child.__proto__ = Parent实现继承
所以理解原型链继承,是读懂现代 JS 类机制的基础。











