圖解JavaScript原型鏈繼承

caihaihong發表於2019-02-24

JavaScript是基於原型鏈的繼承的,忘掉類的繼承,從原型鏈入手。

普通物件 函式物件
  • JavaScrip只有一種結構:物件
  • 通過new Function()建立的物件都是函式物件,其他都是普通物件
  • 每個物件都有 __proto__屬性,,並且該屬性指向原型物件(prototype),但只有函式物件才有 prototype 屬性
prototype和 proto 的概念

prototype是函式的一個屬性(函式都有prototype屬性)指向原型物件。 _ proto_ 是一個物件擁有的內建屬性(請注意:prototype是函式的內建屬性,_ proto_ 是物件的內建屬性),_ proto_ 是JS內部使用尋找原型鏈的屬性。簡單來說,在 javascript 中每個物件都會有一個 _ proto _,方法也是物件,也有這個屬性。 屬性,當我們訪問一個物件的屬性時,如果這個物件內部不存在這個屬性,那麼他就會去 _ proto _ 裡找這個屬性,這個 _ proto _ 又會有自己的 _ proto _,於是就這樣一直找下去,也就是我們平時所說的原型鏈的概念.

image

image
(上圖引用自其他部落格以方便理解)

原型鏈
  • 屬性查詢機制: 當查詢物件的屬性時,如果例項物件自身不存在該屬性,則沿著原型鏈往上一級查詢,找到時則輸出,不存在時,則繼續沿著原型鏈往上一級查詢,直至最頂級的原型物件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()可以判斷某個物件本身是否有某個屬性,函式也是物件。

相關文章