03原型与继承
JS 没有传统 class 的「复制式继承」,它靠原型链(Prototype Chain)共享方法。
搞懂 __proto__ 与 prototype 的区别、new 到底做了什么、
class 只是语法糖——你就打通了 JS 对象模型的任督二脉。
一、对象的「隐藏指针」:__proto__
每个对象都有一个内部槽 [[Prototype]](浏览器暴露为 __proto__),
指向另一个对象。属性查找时,自己没有就顺着这条链往上找。
实例 obj
自己的属性:name = '小明'
↑ __proto__ 找不到 name 就往上
原型 Person.prototype
共享方法:sayHi() { … }
↑ 再往上
Object.prototype
toString / hasOwnProperty / valueOf …
↑ 最顶上是 null
属性查找沿原型链:自己没有 sayHi,却能调用——方法在原型上
点击按钮
__proto__ 是历史遗留,面试爱问,生产代码用
Object.getPrototypeOf(obj) / Object.setPrototypeOf() 更规范。二、prototype vs __proto__:别再搞混
prototype | __proto__ | |
|---|---|---|
| 谁有 | 只有函数有 | 所有对象(含函数)都有 |
| 是什么 | 将来 new 出来的实例的原型 |
自己指向的原型对象 |
| 关系 | instance.__proto__ === Fn.prototype |
|
三、new 的四个步骤
写 const p = new Person('小明') 时,引擎做了四件事:
- 创建一个空对象
{} - 把这个对象的
__proto__指向Person.prototype - 以该对象为
this执行构造函数(挂上 name 等属性) - 如果构造函数没返回对象,就返回这个新对象
手写一个 miniNew:和真 new 对比结果,看四步在代码里长什么样
点击按钮
四、class:原型的语法糖
ES6 的 class 底层还是原型链,但写起来像传统 OOP。
constructor、方法、extends、super 都会映射到原型操作。
class 继承实战:Animal → Dog,看方法覆盖、super 调用、instanceof 链
点击按钮
五、继承的三种写法演进
| 时代 | 写法 | 评价 |
|---|---|---|
| ES5 原型 | Child.prototype = Object.create(Parent.prototype) |
底层原理,面试要懂 |
| ES5 寄生组合 | 借用构造 + 原型桥接 | 最完美的 ES5 方案 |
| ES6 class | class Child extends Parent |
项目首选,语法清晰 |
真实项目直接写
class / 组合优于继承。
原型链是「知其所以然」——排查 instanceof、方法找不到、框架源码时用得上。六、几个高频判断 API
| API | 作用 | 注意 |
|---|---|---|
obj instanceof Fn |
obj 的原型链上是否有 Fn.prototype |
跨 iframe 会误判 |
obj.hasOwnProperty(k) |
属性是否「自己的」(不在原型上) | for…in 会遍历原型可枚举属性 |
Object.getPrototypeOf(o) |
安全读原型 | 替代 __proto__ |
Object.create(proto) |
指定原型创建对象 | 实现继承的基石 |
'k' in obj |
自己或原型上是否存在 | 比 hasOwnProperty 范围大 |
instanceof / hasOwnProperty / in 的差异:同一个属性三种判断结果可能不同
点击按钮
七、组合优于继承
深继承链(A→B→C→D)会让代码变得僵硬。现代实践更推荐 组合(Composition):把能力做成小模块,按需拼装。
八、本章小结
- 属性查找沿原型链向上;自己没有就找
__proto__。 prototype是函数才有(给 new 出的实例准备的原型);__proto__是每个对象的原型指针。new四步:建对象 → 接原型 → 执行构造 → 返回对象。class/extends是原型的语法糖,项目首选。hasOwnProperty只认自己的;in/instanceof会看原型链。- 深层继承僵硬时,优先考虑组合。
动手练习:
① 手写
Object.create 的简化版(指定原型创建对象);
② 用 class 写一个 Shape 基类和 Circle 子类,子类覆盖面积方法并用 super 复用描述方法;
③ 画出 const d = new Dog() 的原型链关系图。