[[Prototype]] 可以理解为 prototype linkage(原型连接),是一种Javascript语言的机制。
prototype、constructor是某些对象上的属性。
接下来可以通过一个函数开始理解
function Foo(name){
this.name = name;
}
Javascript内部会创建一个Foo function, 该 Foo 会有一个prototype的属性(所有的函数都会拥有一个名为prototype的公有并且不可枚举的属性),Foo.prototype
会指向一个匿名对象,这个对象默认会有一个constructor属性,这个属性引用的是对象关联的函数,这个对象关联的函数就是Foo。所以 Foo.prototype.constructor===Foo
的结果为true。
每一个普通对象都有内置的Object.prototype,指向原型链的顶端。像toString()、valueOf()...这些方法都存在于Object.prototype对象上,因此语言中所有对象都可以使用它们。
Foo 函数也是对象,所以它Foo.prototype所指向的那个对象也会关联到Object.prototype,这个就是所谓的原型链的最顶端。(原型链下面会解释)
接下来再看一下代码
Foo.prototype.whoIam(){
return "I am "+ this.name;
}
var a = new Foo('chen');
a.whoIam(); // 'I am chen'
new Foo() 会生成一个新对象,称为a,这对象的内部链接[[Prototype]]会关联到 Foo.prototype上。实际上a并没有whoIam,它会通过委托再Foo.prototype上找到。a对象为什么会有name属性,通过this的绑定得到的(Foo function 里的 this.name=name
)
那么其实就是在第一个对象上没有找到需要的属性或者方法引用,引擎就会继续在[[Prototype]]关联的对象上进行查找。同理后者也没有找到需要的属性或者方法引用就会继续查找它[[Prototype]]关联的对象上进行查找,如果一直找不到,最终查找到Object.prototype对象上。这一系列的行为就是所谓的原型链。
看完上面的图之后就可以更好的理解下来的代码了
a.constructor === Foo.prototype.constructor // true
a.constructor === Foo //true
实际上a 并没有 constructor这个属性,是a 通过[[Prototype]]关联到了 Foo.prototype上,而Foo.prototype 上有constructor这个属性,然后Foo.prototype.constructor引用的是Foo。
那么创建一个普通的a对象也是一样的
var a = {};
a.constructor===Object.prototype.constructor //true