原型链是什么?

91 阅读2分钟

解释原型链

假设我们有一个普通对象x = {},这个x会拥有一个隐藏属性,暂且称之为_?????_,这个属性会指向Object.prototype,即:

x._?????_ === Object.prototype

此时我们说x的原型是Object.prototype,或者说Object.prototypex的原型。
而这个隐藏属性_?????_的唯一作用就是用来指向x的原型的。

接下来我们说说原型链
假设我们有一个数组对象a = [],这个a也会有一个隐藏属性_?????_,这个属性会指向Array.prototype,即:

a._?????_ === Array.prototype

此时我们说a的原型是 Array.prototype,跟上面的x相似,但又不完全一样。
因为Array.prototype也有隐藏属性_?????_,指向Object.prototype,即:

Array.prototype._?????_ === Object.prototype

如此一来,a就具有两层原型:

  1. a的原型是Array.prototype
  2. a的原型的原型是Object.prototype 即通过隐藏属性_?????_串起了这么一个链条:
a ===> Array.prototype ===> Object.prototype

这条链条就是原型链。

想改变/创建原型(链)?

看起来只要直接改写x的隐藏属性_?????_就可以改变x的原型

x._?????_ = 新的原型

但其实官方推荐写法是:

const x = Object.create(新的原型)
// 或者
const x = new 构造函数() // 结果就是 x._?????_ === 构造函数.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

最后,_?????_是个啥

其实这个隐藏属性的真面目是 _proto_
为啥一开始不说呢,proto 和 prototype 翻译成中文都叫原型,在没理解原型链的时候容易混淆,所以干脆先忽略它的名字