原型链涉及的概念有很多,不如举例来说明一下吧
假如有一个普通对象 x={}, 则 x 会有一个隐藏属性 proto, 且
x.__proto__ === Object.prototype
则我们说 x 的原型是 Object.prototype, 在 Object.prototype 中有对象的公共方法, 比如 hasOwnProperty, isPrototypeOf 等
再比如有一个普通数组 a=[], 则 a 有一个默认属性 proto, 且
a.__proto__ === Array.prototype
Array.prototype 也有一个隐藏属性 proto, 且
Array.prototype.__proto__ === Object.prototype
即 a 的原型是 Array.prototype,
a 的原型的原型是 Object.prototype,
通过隐藏属性proto形成了原型链
原型链有什么用呢?
原型链在没有 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 是 ES6 引入的,不被旧 IE 浏览器支持。
指定原型的方法:
看起来只要改写 x 的隐藏属性 proto 就可以改变 x 的原型
x.__proto__ = 原型
但是这不是标准推荐的写法
推荐的写法是
const x = Object.create(原型) // x.__proto__ === 原型
// 或
const x = new 构造函数() // x.__proto__ === 构造函数.prototype