? 圖解原型和原型鏈

JS菌發表於2019-03-14

20190314150227.png

圖解原型和原型鏈

原型和原型鏈是 JS 中不可避免需要碰到的知識點?,本文使用圖片思維導圖的形式縷一縷原型、原型鏈、例項、建構函式等等概念之間的關係?

Constructor 建構函式

首先我們先寫一個建構函式 Person,建構函式一般為了區別普通函式要求首字母大寫:

function Person(){}
複製程式碼

prototype 原型

原型指的就是一個物件,例項“繼承”那個物件的屬性。在原型上定義的屬性,通過“繼承”,例項也擁有了這個屬性。“繼承”這個行為是在 new 操作符內部實現的。

先不說例項,原型與建構函式的關係就是,建構函式內部有一個名為 prototype 的屬性,通過這個屬性就能訪問到原型:

20190314132908.png

Person 就是建構函式,Person.prototype 就是原型

20190314132934.png

instance 例項

有個建構函式,我們就可以在原型上建立可以“繼承”的屬性,並通過 new 操作符建立例項

20190314141908.png

比方說 Person,我們要建立一個 person 例項,那麼使用 new 操作符就可以實現,並通過 instanceof 來檢查他們之間的關係:

20190314132309.png

我們在原型上定義一個屬性,那麼例項上也就可以“繼承”這個屬性:

20190314133215.png

proto 隱式原型

例項通過 __proto__ 訪問到原型,所以如果是例項,那麼就可以通過這個屬性直接訪問到原型:

20190314141947.png

所以這兩者是等價的:

20190314142041.png

constructor 建構函式

既然建構函式通過 prototype 來訪問到原型,那麼原型也應該能夠通過某種途徑訪問到建構函式,這就是 constructor:

20190314142246.png

因此兩者的關係應該是這樣:

20190314142755.png

注意這裡的 constructor 是原型的一個屬性,Constructor 指的才是真正的建構函式。兩者名字不要弄混了?

例項、建構函式、原型之間的關係

這裡我們可以看到如果例項想要訪問建構函式,那麼應當是:

20190314143125.png

沒有從例項直接訪問到建構函式的屬性或方法:

20190314143254.png

例項與原型則是通過上文中提到的 __proto__ 去訪問到。

在讀取一個例項的屬性的過程中,如果屬性在該例項中沒有找到,那麼就會循著 __proto__ 指定的原型上去尋找,如果還找不到,則嘗試尋找原型的原型?:

20190314143837.png

我們把註釋刪掉,給例項同名屬性,可以看到列印出來的屬性就指向這個:

20190314143944.png

原型鏈

原型同樣也可以通過 __proto__ 訪問到原型的原型,比方說這裡有個建構函式 Person 然後“繼承”前者的有一個建構函式 People,然後 new People 得到例項 p

當訪問 p 中的一個非自有屬性的時候,就會通過 __proto__ 作為橋樑連線起來的一系列原型、原型的原型、原型的原型的原型直到 Object 建構函式為止。

這個搜尋的過程形成的鏈狀關係就是原型鏈

20190314144733.png

如下圖:

20190314145239.png

看到 null 了麼,原型鏈搜尋搜到 null 為止,搜不到那訪問的這個屬性就是不存在的:

20190314145540.png

以上,這就是原型、原型鏈、建構函式、例項、null 之間的關係。

? 圖解原型和原型鏈

相關文章