JavaScript對象系統深入剖析(一)
@吳穹Adam (新浪微博)
在學習JavaScript的過程中,經常被它的對象系統(Object,Function,Prototype)搞的雲裡霧裡的,感覺這些東西如果不搞清楚,後續的JavaScript學習也會不紮實,所以,下決心把它搞清楚,讓我們開始吧!
這個學習過程中,主要的參考書目是《JavaScript: The Good Parts》、《JavaScript: The Definitive Guide》和《Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications, and libraries》;主要的分析工具是IE和IE開發人員工具。
1. 對象
JavaScript語言沒有類的概念,除了基本類型(Number、String、booleans、null和undefined)之外,一切都是對象。對象的定義如下,用英文比較準確:
- Objects are mutable keyed collections.
- An object is a container of properties, where a property has a name and a value.
- A property name can be any string, including the empty string.
- A property value can be any JavaScript value except for undefined.
這些都不難理解,關鍵是這個:
- Object includes a prototype linkage feature that allows one object to inherit the properties of another.
這裡,這個原型連結(a prototype linkage)是隱藏的(在Debugger裡面看不見的),在某些實現中,它的屬性名稱是__proto__
因此,到目前為止,JavaScript對象系統用UML建模後的領域模型如下:
補充一下,任何一個對象的__proto__連結都是不為空白的,對於一個從Object Literal中建立的對象,其__proto__指向Object.prototype。
有了__proto__連結之後,就可以發揮一些物件導向的威力了,頭一個就是Delegation。Delegation是指當從一個對象中擷取一個屬性失敗時,JS會自動再嘗試去其__proto__連結指向的對象中去尋找,如果還找不到,就沿著__proto__一路找上去,指導找到Object.prototype為止。根據上述Delegation演算法的描述,你可以很容易理解Delegation過程是動態,這次可以從祖先中找到A屬性,不代表下次一定能找到。
這裡需要注意的是,__proto__連結只對查詢有效,而對Update無效,也就是說,如果你給一個屬性賦值的話,而這個屬性在該對象中還不存在,而在__proto__祖先中已有同名屬性,但這是JS會在該對象中再建立一個屬性,而不是修改祖先的屬性值。
補記:推薦大家去看一下這個部落格,解釋的會更詳細,有更多例子: http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html