Prototype
Prototype是Javascript對象內(nèi)置的一個特殊屬性,這個屬性其實就是對其他對象的引用。當(dāng)你試圖訪問一個對象的某個屬性時,會觸發(fā)[[get]]操作,先在該對象里檢查屬性是否存在,存在的話就可以交差了,如果不存在,[[get]]會繼續(xù)訪問該對象的prototype鏈,檢查prototype鏈中的對象中是不是存在要訪問的屬性。如果prototype鏈都檢查完了直到Object.prototype還沒有找到,那只能返回個undefined,讓你另請高明了。下面看個小李子:
var obj = {
a:2
};
var myobj = Object.create(obj);
myobj.a;//2
上面,obj是個對象,myobj是一個通過Object.create()關(guān)聯(lián)到obj的對象,當(dāng)使用myobj.a訪問屬性a時,在對象obj里沒有屬性a(為什么沒有屬性a?),就會去檢查prototype鏈中的obj,這才找到屬性a。
屬性設(shè)置和屏蔽
既然有prototype機制存在,那對一個對象的屬性賦值是怎么樣的呢?例如下面這條語句:
obj.attr = 2;
首先會去檢查attr屬性,如果屬性attr在包含在對象obj中,那么會直接進(jìn)行賦值操作,如果不在對象obj中,就會開始檢查prototype鏈,prototype鏈中如果存在普通數(shù)據(jù)訪問屬性attr(未被標(biāo)記為只讀,如果標(biāo)記為只讀,會報錯),就會在對象obj中新建屬性attr并賦值2,就屏蔽了prototype鏈中的屬性attr。
類?不存在的! JS中只有對象
js中其實是不存在類的,但是卻存在一些模仿類的語法,像下面:
function Foo(){
//todo
}
var foo = new Foo();
像這種怎么解釋呢?Foo不是類嗎?都用new了?
在面向類的語言中,實例化一個類會把類的屬性和方法復(fù)制到實例中,而javascript中并不存在這樣的復(fù)制機制。這里的new很容易讓我們聯(lián)想到一些語言中也存在的關(guān)鍵字new,通過調(diào)用類的構(gòu)建函數(shù)constructor創(chuàng)建實例。
其實new Foo();語句只是新建了對象foo,期間給foo一個內(nèi)部的prototype鏈接,關(guān)聯(lián)到Foo.prototype指向的對象。new在兩個對象之間建立了關(guān)聯(lián)(Object.create()也可以)。這樣一個對象就可以通過這種關(guān)聯(lián)委托訪問到另一個對象的屬性和函數(shù)。那對象foo是怎么創(chuàng)建的呢?同樣對象foo的構(gòu)造函數(shù)constructor也委托到prototype鏈上,但對象Foo里也找不到constructor,這樣沿著prototype鏈找到了頂端的 Object.constructor。例證如下,考慮下面代碼和運行截圖:
function Foo() {
//todo
}
Foo.prototype = {
//todo
}; // 創(chuàng)建一個新原型對象
var a1 = new Foo();

可見,對象
foo的構(gòu)造函數(shù)委托到了Object.constructor。至此,你所看到的javascript中的“類”都是假象,是的,就像《百年孤獨》里說的那樣,“一切都是假的”。
new還是Object.create()?
Prototype機制就是存在于對象中的一個內(nèi)部鏈接,它會引用其他對象。
通常來說,這個鏈接的作用是:如果在對象上沒有找到需要的屬性或者方法引用,引擎就會繼續(xù)在Prototype關(guān)聯(lián)的對象上進(jìn)行查找。同理,如果在后者中也沒有找到需要的引用就會繼續(xù)查找它的Prototype,以此類推。這一系列對象的鏈接被稱為“原型鏈”。
既然new和Object.create()都可以創(chuàng)建這種關(guān)聯(lián),兩者之間區(qū)別何在呢?主要區(qū)別是使用new時會生成.prototype和.constructor的引用,相比之下,Object.create()就純粹的多,只是憑空創(chuàng)建一個新的對象并簡歷關(guān)聯(lián)。
這篇入門級的讀書筆記就先寫到這里,如有錯誤,懇請指正,溜了溜了...