解释原型链
假设我们有一个普通对象x = {},这个x会拥有一个隐藏属性,暂且称之为_?????_,这个属性会指向Object.prototype,即:
x._?????_ === Object.prototype
此时我们说x的原型是Object.prototype,或者说Object.prototype是x的原型。
而这个隐藏属性_?????_的唯一作用就是用来指向x的原型的。
接下来我们说说原型链。
假设我们有一个数组对象a = [],这个a也会有一个隐藏属性_?????_,这个属性会指向Array.prototype,即:
a._?????_ === Array.prototype
此时我们说a的原型是 Array.prototype,跟上面的x相似,但又不完全一样。
因为Array.prototype也有隐藏属性_?????_,指向Object.prototype,即:
Array.prototype._?????_ === Object.prototype
如此一来,a就具有两层原型:
a的原型是Array.prototypea的原型的原型是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为例:
a是Array的实例,a拥有Array.prototype里的属性Array继承了Object- 所以
a是Object的间接实例,a拥有Object.prototype里的属性
结果就是,a既拥有Array.prototype里的属性,也拥有Object.prototype里的属性
优点:使用简单
缺点:跟 class 相比,不支持私有属性
想解决缺点?直接用 class 吧。只不过 class 是 ES6 引入的,不支持旧的 IE
最后,_?????_是个啥
其实这个隐藏属性的真面目是 _proto_
为啥一开始不说呢,proto 和 prototype 翻译成中文都叫原型,在没理解原型链的时候容易混淆,所以干脆先忽略它的名字