JavaScript继承本质是原型链,ES6 class仅为语法糖;组合继承通过构造函数继承属性+Object.create继承方法实现,需修复constructor指向,避免直接赋值prototype。

JavaScript 中没有原生的“类继承”概念,但可以通过原型链模拟传统面向对象语言(如 Java、C++)中的继承行为。ES6 引入了 class 语法,但它只是语法糖,底层仍基于原型链。理解原型链继承,是掌握 JS 面向对象本质的关键。
用 prototype 和 constructor 手动构建继承关系
核心思路:让子构造函数的 prototype 对象指向父构造函数的一个实例(或通过 Object.create() 创建其原型的副本),再修正 constructor 指向。
- 定义父构造函数,并在其
prototype上添加方法 - 定义子构造函数,在其内部调用
Parent.call(this, ...)实现属性继承(借用构造函数) - 设置子类原型为父类原型的副本:
Child.prototype = Object.create(Parent.prototype) - 恢复子类原型的
constructor:Child.prototype.constructor = Child
示例:
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); // 继承原型方法
Dog.prototype.constructor = Dog; // 修复 constructor
Dog.prototype.speak = function() {
console.log(`${this.name} barks!`);
};
避免直接赋值 Child.prototype = Parent.prototype
这种写法会让子类和父类共享同一份原型对象,修改 Dog.prototype 会意外影响 Animal.prototype,破坏封装性。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- 错误写法:
Dog.prototype = Animal.prototype - 正确做法始终用
Object.create(Parent.prototype)或Object.setPrototypeOf(Dog.prototype, Animal.prototype) - 现代推荐使用
Object.create,语义清晰且兼容性好
组合继承:兼顾实例属性与原型方法的完整继承
上面的手动方式就是“组合继承”——构造函数继承 + 原型链继承。它能同时复用父类的实例属性初始化逻辑和原型方法,是 ES5 中最常用、最可靠的继承模式。
- 优点:子实例有自己的一份实例属性,又可访问父类原型方法
- 缺点:父构造函数会被调用两次(一次在
Object.create时,一次在Animal.call时),但实际影响极小,可接受 - 若追求极致优化,可用“寄生组合式继承”(即只调用一次父构造函数),但日常开发中组合继承已足够
ES6 class 的本质仍是原型链
class 语法让继承更简洁,但编译后依然靠原型链运行:
class Animal {
constructor(name) { this.name = name; }
speak() { console.log(`${this.name} makes a sound.`); }
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 等价于 Animal.call(this, name)
this.breed = breed;
}
speak() { console.log(`${this.name} barks!`); }
}
执行时,JS 引擎会自动设置 Dog.prototype.__proto__ === Animal.prototype,并确保 super() 正确绑定 this。这背后全是原型链在工作。

















