原型链
是什么
每个对象都拥有一个原型对象,该对象以原型为模版、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
举例
比如 const a = []
,a
的原型是 Array.prototype
,Array.prototype
的原型是 Object.prototype
,Object.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
为例,我们说:
a
是Array
的实例,a
拥有Array.prototype
里的属性。Array
继承了Object
(注意专业术语的使用)a
是Object
的间接实例,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
任何函数有Object
、Array
、Function
。