JavaScript是基於原型鏈的繼承的,忘掉類的繼承,從原型鏈入手。
普通物件 函式物件
- JavaScrip只有一種結構:物件
- 通過new Function()建立的物件都是函式物件,其他都是普通物件。
- 每個物件都有
__proto__
屬性,,並且該屬性指向原型物件(prototype),但只有函式物件才有 prototype 屬性
prototype和 proto 的概念
prototype是函式的一個屬性(函式都有prototype屬性)指向原型物件。 _ proto_ 是一個物件擁有的內建屬性(請注意:prototype是函式的內建屬性,_ proto_ 是物件的內建屬性),_ proto_ 是JS內部使用尋找原型鏈的屬性。簡單來說,在 javascript 中每個物件都會有一個 _ proto _,方法也是物件,也有這個屬性。 屬性,當我們訪問一個物件的屬性時,如果這個物件內部不存在這個屬性,那麼他就會去 _ proto _ 裡找這個屬性,這個 _ proto _ 又會有自己的 _ proto _,於是就這樣一直找下去,也就是我們平時所說的原型鏈的概念.
(上圖引用自其他部落格以方便理解)原型鏈
- 屬性查詢機制: 當查詢物件的屬性時,如果例項物件自身不存在該屬性,則沿著原型鏈往上一級查詢,找到時則輸出,不存在時,則繼續沿著原型鏈往上一級查詢,直至最頂級的原型物件Object.prototype,如還是沒找到,則輸出undefined。
- 屬性修改機制: 只會修改例項物件本身的屬性,如果不存在,則進行新增該屬性,如果需要修改原型的屬性時,則可以用: b.prototype.x = 2;但是這樣會造成所有繼承於該物件的例項的屬性發生改變。
表示式:L instance R;
則運算結果是: L.__proto__.__proto__... === R.prototype ?
運算子左邊最終結果是 instanceof運算時會遞迴查詢L的原型鏈,即L.__proto__.__proto__.__proto__.__proto__...直到找到了或者找到頂層為止。
運算子右邊只是找出了 右邊運算元的prototype是什麼。
所以一句話總結:instanceof檢測左側運算元的__proto__原型鏈上,是否存在右側的prototype原型。
複製程式碼
總結
- Function的兩個指標prototype和_ proto _ 均指向 Function.protptype
- 建構函式通過prototype屬性獲取原型物件。
- 原型物件通過constructor屬性獲取建構函式
- 物件通過
__proto__
(非標準,隱式原型)屬性獲取原型物件。 - 建構函式的prototype(標準,顯式原型)屬性指向上一級原型物件直到Object原型物件。
- Object.prototype.__proto__指向null
- 所有的物件最終都繼承於Object.prototype,而所有的建構函式,包括Function(){} Object(){}在內,又都可以看做是Function的例項
- Obj.hasOwnProperty()可以判斷某個物件本身是否有某個屬性,函式也是物件。