[[Prototype]]

81 阅读2分钟

普通对象在创建的时候,对象中都会存在[[Prototype]]内置属性。它的作用是指向新创建对象的关联对象。

我们都知道,当访问一个对象的属性时,如果当前对象并不存在这个属性,但是[[Prototype]]内置属性所指向的对象中存在这个属性的话,同样可以获取到该属性的值。

思考如下代码:

let myObject = {
  a: 1
}
const createObject = Object.create(myObject)
console.log(createObject.a) // 1

这里createObject对象中其实并没有创建属性a的值,但是输出结果仍然是1。这就是因为createObject对象是基于myObject对象来创建的,creatObject对象的[[Prototype]]属性指向了关联的myObject对象。同理,这种引用可能会存在多层,一层一层的引用,这就是大家熟悉的原型链,当访问的直接对象中没有要访问的属性时,就会沿着对象的[[Prototype]]属性一层层往上找,直至最上层。

Object.prototype

刚说到当直接对象中不存在要访问的属性,会沿着原型链往上逐层查找,直到找到该属性值,或到了最顶层仍未找到就结束查找过程。那最顶层是什么呢?

Object.prototype,一切对象的终点。

所以说,像我们常用的keys()、create()、toString()、valueOf()等方法,都在Object.prototype对象中定义。刚不是说它是一切对象的终点,那任何对象的创建直接或间接基于它的话,都能获取到这些方法。

面向对象中的类,如Java,它们继承一个父类,都是复制一个父类,而在JavaScript中,本质上并不是复制出一个新对象,而是基于一个对象来生成的,它们间还存在关联关系。当然也可以做到完全创造出一个新对象。

获取对象属性的规则比较简单,我们基本清楚了,无非就是当前访问对象若不存在,则跟着原型链继续找,直至找到或到顶都没有找到而结束。反过来想想,当我们要设置对象的某个属性值时,它是否存在于当前对象或原型链中,规则又有什么区别呢?