原型
每一個 js 物件都有一個proto屬性,這個屬性指向了原型
,這個屬性在現在來說已經不建議直接使用了,這是瀏覽器在早期為了讓我們訪問到內部屬性[[prototype]]
來實現的一個東西.
講到這裡好像還是沒明白什麼是原型,接下來我們根據圖來看看proto都有些啥:
看了上圖你應該明白了吧,原型
也是一個物件
,並且這個物件中包含了很多函式,所有我們可以得出一個結論:對於obj
來說,可以通過__proto__
找到了一個原型物件
,且原型物件
中定義了很多函式讓我們來使用.
另外,從圖片上我還發現了一個constructor
屬性,也就是建構函式
.
結論:obj.__proto__.constructor === Object
.
接下來,我們展開原型的 constructor 屬性指向了建構函式
obj.__proto__.constructor
屬性,發現其中還有一個prototype
屬性,並且這個屬性對應的值和先前在obj.__proto__
中看到的一樣.
得出結論:
- 物件的
__proto__
屬性指向了原型
; 原型
的constructor
屬性又指向了建構函式
;建構函式
又通過它的prototype
屬性指回了原型
;
::: warning
並不是所有函式都具有constructor
屬性,如:Function.prototype.bind()
:::
原型鏈
接下來我們根據下面這張圖來看看原型
和原型鏈
等關係,徹底搞明白它.
看完這張圖,接下來我們就來解釋下什麼是原型鏈
吧.
其實,原型鏈
就是多個物件通過__proto__
屬性的方式連結了起來.
為什麼obj
物件可以訪問到valueOf
函式,因為obj
通過原型鏈找到了valueOf
函式.
看圖梳理下:
-
__proto__
:是物件
就會有這個屬性(強調是物件);函式
也是物件,那麼函式也有這個屬性咯,它指向建構函式
的原型物件; -
prototype
:是函式
都會有這個屬性(強調是函式),普通物件
是沒有這個屬性的(JS 裡面,一切皆為物件,所以這裡的普通物件
不包括函式物件
).它是建構函式的原型物件; -
constructor
:這是原型物件
上的一個指向建構函式
的屬性。
總結:
- 每一個物件都有
__proto__
屬性,__proto__
==>Object.prototype
(Object 建構函式的原型物件); - 每個函式都
__proto__
和prototype
屬性; - 每個
原型物件
都有constructor
和__proto__
屬性,其中constructor
指回'建構函式', 而__proto__
指向Object.prototype
; object
是有物件的祖先,所有物件都可以通過__proto__
屬性找到它;Function
是所有函式的祖先,所有函式都可以通過__proto__
屬性找到它;- 每個函式都有一個
prototype
,由於prototype
是一個物件,指向了建構函式的原型物件 - 物件的
__proto__
屬性指向原型
,__proto__
將物件和原型連結起來組成了原型鏈