JavaScript类继承本质是原型链继承的语法糖,class通过隐式操作prototype和__proto__实现继承,new子类实例后能访问父类方法因原型链存在,手动实现需显式设置__proto__并修复constructor。

JavaScript 中的继承不是“选哪种更好”,而是“类继承就是原型链继承的语法糖”——class 写法背后仍是操作 prototype 和 __proto__,只是隐藏了手动赋值、修正 constructor 等细节。
为什么 new 一个子类实例后,能访问父类原型上的方法?
因为实例的 __proto__ 指向子类的 prototype,而子类 prototype.__proto__ 又指向父类 prototype,形成原型链。方法查找时沿这条链向上遍历。
手动实现时容易漏掉关键一步:
- 子类
prototype必须显式设置__proto__(或用Object.setPrototypeOf())指向父类prototype - 否则子类实例无法访问父类原型方法,只继承构造函数内定义的属性
-
constructor属性会被覆盖,需手动恢复:Child.prototype.constructor = Child
class extends 和手写 prototype 链的核心差异在哪?
差异不在机制,而在约束和默认行为:
立即学习“Java免费学习笔记(深入)”;
-
class中super()强制调用父类构造函数,且必须在this使用前执行;手写方式不强制,但漏调会导致this未初始化 -
class的子类prototype自动链接到父类prototype,无需手动setPrototypeOf -
class声明不被提升(ReferenceError),函数声明可提升 -
class方法默认不可枚举;手写挂载到prototype上的方法默认可枚举(除非用Object.defineProperty显式设enumerable: false)
使用 Object.create(Parent.prototype) 时要注意什么?
这是最接近 class extends 行为的手写方式,但有几个易错点:
-
Object.create(Parent.prototype)返回的是一个新对象,不能直接赋给Child.prototype后就完事——它会丢失Child自己定义的方法 - 正确做法是:先
Child.prototype = Object.create(Parent.prototype),再往该对象上添加子类方法(或用Object.assign合并) - 必须重置
constructor:Child.prototype.constructor = Child,否则instance.constructor指向Parent - 如果父类构造函数有副作用(如绑定事件、发请求),
Object.create不会执行它——仅建立原型链,不调用构造逻辑
function Parent(name) {
this.name = name;
}
Parent.prototype.say = function() { return 'hi'; };
function Child(name, age) {
Parent.call(this, name); // 手动调用父构造
this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 关键!
Child.prototype.play = function() { return 'game'; };
const c = new Child('Alice', 12);
console.log(c.say()); // 'hi'
console.log(c.play()); // 'game'
console.log(c.constructor === Child); // true
真正难的不是写出能跑的继承,而是理解每次 new 时发生了几层链接、哪些对象被修改、constructor 指针是否断裂——这些地方一错,instanceof 和序列化/调试都会出人意料。











