型對象也是普通的對象,并且也有可能有自己的原型,如果一個原型對象的原型不為null的話,我們就稱之為原型鍊(prototype chain)。
A prototype chain is a finite chain of objects which is used to implemented inheritance and shared properties.
原型鍊是一個由對象組成的有限對象鍊由于實作繼承和共享屬性。
想象一個這種情況,2個對象,大部分内容都一樣,隻有一小部分不一樣,很明顯,在一個好的設計模式中,我們會需要重用那部分相同的,而不是在每個對象中重複定義那些相同的方法或者屬性。在基于類[class-based]的系統中,這些重用部分被稱為類的繼承 – 相同的部分放入class A,然後class B和class C從A繼承,并且可以聲明擁有各自的獨特的東西。
ECMAScript沒有類的概念。但是,重用[reuse]這個理念沒什麼不同(某些方面,甚至比class-更加靈活),可以由prototype chain原型鍊來實作。這種繼承被稱為delegation based inheritance-基于繼承的委托,或者更通俗一些,叫做原型繼承。
類似于類”A”,”B”,”C”,在ECMAScript中尼建立對象類”a”,”b”,”c”,相應地, 對象“a” 擁有對象“b”和”c”的共同部分。同時對象“b”和”c”隻包含它們自己的附加屬性或方法。
var a = {
x: 10,
calculate: function (z) {
return this.x + this.y + z
}
};
var b = {
y: 20,
__proto__: a
};
var c = {
y: 30,
__proto__: a
};
// 調用繼承過來的方法
b.calculate(30); // 60
c.calculate(40); // 80
這樣看上去是不是很簡單啦。b和c可以使用a中定義的calculate方法,這就是有原型鍊來[prototype chain]實作的。
原理很簡單:如果在對象b中找不到calculate方法(也就是對象b中沒有這個calculate屬性), 那麼就會沿着原型鍊開始找。如果這個calculate方法在b的prototype中沒有找到,那麼就會沿着原型鍊找到a的prototype,一直周遊完整個原型鍊。記住,一旦找到,就傳回第一個找到的屬性或者方法。是以,第一個找到的屬性成為繼承屬性。如果周遊完整個原型鍊,仍然沒有找到,那麼就會傳回undefined。
注意一點,this這個值在一個繼承機制中,仍然是指向它原本屬于的對象,而不是從原型鍊上找到它時,它所屬于的對象。例如,以上的例子,this.y是從b和c中擷取的,而不是a。當然,你也發現了this.x是從a取的,因為是通過原型鍊機制找到的。
如果一個對象的prototype沒有顯示的聲明過或定義過,那麼__prototype__的預設值就是object.prototype, 而object.prototype也會有一個__prototype__, 這個就是原型鍊的終點了,被設定為null。
下面的圖示就是表示了上述a,b,c的繼承關系:

原型鍊
原型鍊通常将會在這樣的情況下使用:對象擁有 相同或相似的狀态結構(same or similar state structure) (即相同的屬性集合)與 不同的狀态值(different state values)。在這種情況下,我們可以使用 構造函數(Constructor) 在 特定模式(specified pattern) 下建立對象。