1.幫你完全搞懂JS中的prototype、__proto__與constructor(圖解)javascript
以前也嘗試總結過 js 中的 __proto__ 、 prototype 以及原型鏈相關的資料(JS 中的原型 -- prototype、__proto__ 以及原型鏈),不過彼時受限於經驗等因素,沒有多少條理,同時也存在諸多的的疑點。html
學習嘛,就是一個不斷推翻本身的過程,本次總結以下:java
如下例子貫穿全文...chrome
function Foo(age) { this.age = age; } let f1 = new Foo(16);
先來張總體圖解(原圖較大,建議新標籤頁內觀看):瀏覽器
看着這花花綠綠的線條,頭真的很大...不過不要緊,分解過來看。函數
注意: 圖中的 '()' 僅表明這是一個函數對象,並不是執行函數運算符。
post
__proto__ 在 ECMA 標準中是 [[Prototype]] ,各家瀏覽器的實現不同,在 chrome 中就是 __proto__ ,稍微留意下便可。學習
__proto__ 屬性,當中存放(指向)着的是一個對象,粗略地講就是以 「{ key: value }」 這種形式存在的對象(這裏主要的爲和 js 中的函數對象區分開來)。this
__proto__ 這個屬性,理應是 「{k: v}」 對象所獨有的,可是由於 js 中萬物皆對象,因此 js 函數也是一種對象,因此函數也一樣擁有這個屬性,也正是由於這樣,極容易產生困惑。
url
咱們從總圖中把 __proto__ 單獨抽出來:
如上圖所示,一個對象(f1)的 __proto__ 指向的另外一個對象的,即指向它們的原型對象(也能夠理解爲父對象)。
這個屬性的做用是當訪問一個對象的屬性時,若是該對象內部不存在這個屬性,那麼就會去它的__proto__屬性所指向的那個對象(父對象)裏找,若是父對象也不存在這個屬性,則繼續往父對象的 __proto__ 屬性所指向的那個對象(爺爺對象)裏找,若是還沒找到,則繼續往上找…直到原型鏈頂端null(原始人。。。),再往上找就至關於在null上取值,會報錯。
經過這樣一種鏈條式的值查找,就是咱們常見的原型鏈,同時,這也是咱們模擬繼承的經常使用方法。
prototype 屬性,函數獨有,其存放(指向)的一樣是一個對象。
從總圖中將 prototype 抽出來:
prototype 中存放的一樣是一個對象,這個對象的含義是函數的原型對象,也就是以這個函數做爲構造函數(其實全部函數均可以做爲構造函數)所建立的實例的原型對象,即 f1.__proto__ === Foo.prototype,這兩個屬性均指向同一個對象。
prototype 的做用是包含能夠由特定類型的全部實例共享的屬性和方法,也就是讓該函數所實例化的對象們均可以找到公用的屬性和方法。任何函數在建立的時候,其實會默認同時建立該函數的prototype對象。
constructor 屬性,和 __proto__ 同樣,理應是對象獨有,不過嘛,由於 js 因此 函數也有,可是不經常使用,故留意下便可。
constructor 屬性(變量),當中存放(指向)的是一個函數。
constructor 中存放的這個函數,就是該對象的構造函數,如對象 f1 以 Foo 爲構造函數,那麼 f1.constructor == Foo // true 。
從上圖中能夠看到,全部的箭頭都指向 Function 這個函數,而且 Function 的 constructor 是指向本身,故 constructor 屬性的重點就是 Function 這個函數。如: Foo.constructor == Function // true 。
從第 三 點咱們知道,任何函數在建立的時候,其實會默認同時建立該函數的prototype對象。而在建立的這個 prototype 對象的時候,其中的 constructor 會顯示指向這個函數,即上圖中的 Foo.prototype.constructor == Foo
以上爲本次總結的內容,若有缺陷,還望斧正。