JavaScript中的對象有一個特殊的[[Prototype]]内置屬性,其實就是對于其他對象的引用。
當你試圖引用對象的屬性時會觸發原型[[Get]]操作,比如myObject.a。
1. 第一步是檢查對象本身是否有這個屬性,如果有的話就使用它。
2. 如果a不在myObject中,就需要使用對象的[[Prototype]]鍊了。
1)Object.prototype
普通的[[Prototype]]鍊最終都會指向内置的Object.prototype。

2)屬性設定和屏蔽
如 果 屬 性 名foo既 出 現 在myObject中 也 出 現 在myObject的[[Prototype]]鍊 上 層, 那麼就會發生屏蔽。
myObject中包含的foo屬性會屏蔽原型鍊上層的所有foo屬性,因為myObject.foo總是會選擇原型鍊中最底層的foo屬性。
有些情況下會隐式産生屏蔽:
++操作相當于myObject.a = myObject.a + 1。
是以++操作首先會通過[[Prototype]]查找屬性a并從anotherObject.a擷取目前屬性值2,然後給這個值加1,接着用[[Put]]将值3賦給myObject中建立的屏蔽屬性a。
JavaScript中隻有對象。
在JavaScript中,類無法描述對象的行,(因為根本就不存在類!)對象直接定義自己的行為。
1)“類”函數
a這個對象是在調用new Foo()時建立的,最後會被關聯到這個“Foo.prototype”對象上。
在JavaScript中不能建立一個類的多個執行個體,隻能建立多個對象,它們[[Prototype]]關聯的是同一個對象。
從視覺角度來說,[[Prototype]]機制如下圖所示,箭頭從右到左,從下到上:
這個機制通常被稱為原型繼承,它常常被視為動态語言版本的類繼承。
2)“構造函數”
之是以認為Foo是一個“類”:
1. 其中一個原因是我們看到了關鍵字new,在面向類的語言中構造類執行個體時也會用到它。
2. 另一個原因是,看起來我們執行了類的構造函數方法,Foo()的調用方式很像初始化類時類構造函數的調用方式。
在JavaScript中對于“構造函數”最準确的解釋是,所有帶new的函數調用。
函數不是構造函數,但是當且僅當使用new時,函數調用會變成“構造函數調用”。
原型繼承的機制,是指a可以“繼承”Foo.prototype并通路Foo.prototype的myName()函數。
面這兩種方式是常見的錯誤做法:
1. 第一種隻是讓Bar.prototype直接引用Foo.prototype對象。是以當你執行類似Bar.prototype.myLabel = ...的指派語句時會直接修改Foo.prototype對象本身。
2. 第二種的确會建立一個關聯到Bar.prototype的新對象。但是它使用了Foo(..)的“構造函數調用”,如果函數Foo有一些副作用(比如寫日志、修改狀态、注冊到其他對象、給this添加資料屬性,等等)的話,就會影響到Bar()的“後代”。
兩種正确的把Bar.prototype關聯到Foo.prototype的方法:
1)檢查“類”關系
在傳統的面向類環境中,檢查一個執行個體(JavaScript中的對象)的繼承祖先(JavaScript中的委托關聯)通常被稱為内省(或者反射)。
如何通過内省找出a的“祖先”(委托關聯)呢?
1. 第一種站在“類”的角度來判斷:
instanceof回答的問題是:在a的整條[[Prototype]]鍊中是否有指向Foo.prototype的對象?
這個方法隻能處理對象(a)和函數(帶.prototype引用的Foo)之間的關系。
2. 第二種判斷[[Prototype]]反射的方法,它更加簡潔:
isPrototypeOf回答的問題是:在a的整條[[Prototype]]鍊中是否出現過Foo.prototype?
同樣的問題,同樣的答案,但是在第二種方法中并不需要間接引用函數(Foo),它的.prototype屬性會被自動通路。
我們隻需要兩個對象就可以判斷它們之間的關系。舉例來說:
2)擷取一個對象的[[Prototype]]鍊
1. 在ES5中,标準的方法是:
2. 浏覽器也支援一種非标準的方法來通路内部[[Prototype]]屬性:
.__proto__的實作大緻上是這樣的:
通路(擷取值)a.__proto__時,實際上是調用了a.__proto__()(調用getter函數)。
雖然getter函數存在于Object.prototype對象中,但是它的this指向對象a,是以和Object.getPrototypeOf( a )結果相同。
[[Prototype]]機制就是存在于對象中的一個内部連結,它會引用其他對象。
這個連結的作用是:如果在對象上沒有找到需要的屬性或者方法引用,引擎就會繼續在[[Prototype]]關聯的對象上進行查找。
這一系列對象的連結被稱為“原型鍊”。
我們并不需要類來建立兩個對象之間的關系,隻需要通過委托來關聯對象就足夠了。
Object.create()的polyfill代碼:
使用了一個一次性函數F,我們通過改寫它的.prototype屬性使其指向想要關聯的對象,然後再使用new F()來構造一個新對象進行關聯。
本文轉自 咖啡機(K.F.J) 部落格園部落格,原文連結:http://www.cnblogs.com/strick/p/5838126.html,如需轉載請自行聯系原作者