原型链继承与原型继承是同一概念,本质都是通过prototype和__proto__实现的继承;Object.create(Parent.prototype)更优,避免父类构造函数副作用和实例属性共享。

原型链继承就是原型继承,二者是同一概念的不同叫法。所谓“原型继承”在 JavaScript 中没有独立于“原型链继承”的实现方式——所有基于 prototype 和 __proto__ 链接对象的继承,本质都是原型链继承。
为什么容易混淆叫法?
部分资料把“用 Object.create(Parent.prototype)”称作“原型式继承”,而把“Child.prototype = new Parent()”叫“原型链继承”。其实两者都依赖原型链,区别只在于创建子类原型的方式:
- new Parent():会执行父类构造函数,可能产生副作用(如初始化共享引用类型属性)
- Object.create(Parent.prototype):不调用父类构造函数,只建立原型链接,更干净、更可控
什么时候该用哪种写法?
优先选 Object.create(Parent.prototype),尤其在需要避免父类构造函数副作用时:
- 父类有初始化逻辑(比如发请求、修改全局状态),你不希望每次设置原型都触发它
- 父类有引用类型实例属性(如
this.arr = []),用new Parent()会导致所有子实例共享该数组 - 你只想继承方法,不继承实例属性(比如纯工具类、抽象基类)
实际代码对比
假设父类定义如下:
function Parent() {
this.name = 'parent';
this.items = [1, 2];
}
Parent.prototype.say = function() { return this.name; };
错误写法(引发共享问题):
function Child() {}
Child.prototype = new Parent(); // ❌ items 被所有 Child 实例共享
const c1 = new Child();
const c2 = new Child();
c1.items.push(3);
console.log(c2.items); // [1, 2, 3] —— 意外被改
推荐写法(解耦原型与实例初始化):
function Child() {}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 修复 constructor 指向
const c1 = new Child();
const c2 = new Child();
console.log(c1.say()); // 'parent' ✅ 方法可继承
console.log(c1.items); // undefined ✅ 不继承实例属性,避免共享
补充说明
ES6 的 class 语法底层仍是原型链继承,只是封装了 Object.create + constructor 修复 + [[Prototype]] 设置等细节。所以不必纠结“选哪个”,重点是理解:继承的是原型上的方法,不是父类实例的属性;属性初始化应放在子类构造函数中。

















