Skip to content

原型链

是什么

每个对象都拥有一个原型对象,该对象以原型为模版从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

举例

比如 const a = []a 的原型是 Array.prototypeArray.prototype 的原型是 Object.prototypeObject.prototype 的原型是 null

那么 a 的原型链就是 a --> Array.prototype --> Object.prototype --> null

怎么做(如何修改原型链)

看起来只要改写 a 的隐藏属性 __?????__ 就可以改变 a 的原型(链)

js
a.__?????__ = 原型

但是这不是标准推荐的写法,为了设置 a.__?????___ ,推荐的写法是

js
const a = Object.create(原型)
// 或
const a = new 构造函数() // 会导致 a.__?????__ === 构造函数.prototype

解决了什么问题

在没有 Class 的情况下实现「继承」。以 a ===> Array.prototype ===> Object.prototype 为例,我们说:

  1. aArray 的实例,a 拥有 Array.prototype 里的属性。
  2. Array 继承了 Object(注意专业术语的使用)
  3. aObject 的间接实例,a 拥有 Object.prototype 里的属性。这样一来,a 就既拥有 Array.prototype 里的属性,又拥有 Object.prototype 里的属性。

优点是什么

简单、优雅。

缺点是什么

class 相比,不支持私有属性。

如何解决缺点

使用 class 呗。但 class 是 ES6 引入的,不被旧 IE 浏览器支持。

prototype 和 proto([[Prototype]])区别是什么

都存着原型的地址,只不过 prototype 挂在函数的上,__proto__([[Prototype]]) 挂在每个新生成的对象上。

总结

  • JS公式对象.__proto__ === 其构造函数.prototype
  • 根公理Object.prototype所有对象的(直接或间接)原型,即 Object.prototype.__proto__ === null
  • 函数公理: 所有函数都是由 Function 构造的,任何函数. __proto__ === Function.prototype 任何函数有 ObjectArrayFunction

参考资料

JS原型

JS 中 proto 和 prototype 存在的意义