[[Prototype]] 可以理解為 prototype linkage(原型連接),是一種Javascript語言的機(jī)制。
prototype、constructor是某些對(duì)象上的屬性。
接下來可以通過一個(gè)函數(shù)開始理解
function Foo(name){
this.name = name;
}
Javascript內(nèi)部會(huì)創(chuàng)建一個(gè)Foo function, 該 Foo 會(huì)有一個(gè)prototype的屬性(所有的函數(shù)都會(huì)擁有一個(gè)名為prototype的公有并且不可枚舉的屬性),Foo.prototype會(huì)指向一個(gè)匿名對(duì)象,這個(gè)對(duì)象默認(rèn)會(huì)有一個(gè)constructor屬性,這個(gè)屬性引用的是對(duì)象關(guān)聯(lián)的函數(shù),這個(gè)對(duì)象關(guān)聯(lián)的函數(shù)就是Foo。所以 Foo.prototype.constructor===Foo 的結(jié)果為true。
每一個(gè)普通對(duì)象都有內(nèi)置的Object.prototype,指向原型鏈的頂端。像toString()、valueOf()...這些方法都存在于Object.prototype對(duì)象上,因此語言中所有對(duì)象都可以使用它們。
Foo 函數(shù)也是對(duì)象,所以它Foo.prototype所指向的那個(gè)對(duì)象也會(huì)關(guān)聯(lián)到Object.prototype,這個(gè)就是所謂的原型鏈的最頂端。(原型鏈下面會(huì)解釋)
接下來再看一下代碼
Foo.prototype.whoIam(){
return "I am "+ this.name;
}
var a = new Foo('chen');
a.whoIam(); // 'I am chen'
new Foo() 會(huì)生成一個(gè)新對(duì)象,稱為a,這對(duì)象的內(nèi)部鏈接[[Prototype]]會(huì)關(guān)聯(lián)到 Foo.prototype上。實(shí)際上a并沒有whoIam,它會(huì)通過委托再Foo.prototype上找到。a對(duì)象為什么會(huì)有name屬性,通過this的綁定得到的(Foo function 里的 this.name=name)
那么其實(shí)就是在第一個(gè)對(duì)象上沒有找到需要的屬性或者方法引用,引擎就會(huì)繼續(xù)在[[Prototype]]關(guān)聯(lián)的對(duì)象上進(jìn)行查找。同理后者也沒有找到需要的屬性或者方法引用就會(huì)繼續(xù)查找它[[Prototype]]關(guān)聯(lián)的對(duì)象上進(jìn)行查找,如果一直找不到,最終查找到Object.prototype對(duì)象上。這一系列的行為就是所謂的原型鏈。
看完上面的圖之后就可以更好的理解下來的代碼了
a.constructor === Foo.prototype.constructor // true
a.constructor === Foo //true
實(shí)際上a 并沒有 constructor這個(gè)屬性,是a 通過[[Prototype]]關(guān)聯(lián)到了 Foo.prototype上,而Foo.prototype 上有constructor這個(gè)屬性,然后Foo.prototype.constructor引用的是Foo。
那么創(chuàng)建一個(gè)普通的a對(duì)象也是一樣的
var a = {};
a.constructor===Object.prototype.constructor //true