用小豬佩奇說明Javascript的原型和原型鏈

  沒錯,我就是標題黨!你已經成功被我騙進來了。來都來了,那就聊聊再走唄!接下來就聽我一本正經地跟你說道說道。javascript

  Javascript的原型是這門語言的一個重點和難點。看過不少大佬寫的解釋Javascript原型的文章,可是不少對於初學者其實不是很友好,看完以後仍是雲裏霧裏。我雖然不敢說能把這個東西解釋的很清楚,可是做爲一個前端菜鳥,我可能更知道你們在讀文章的時候會卡在哪一步,因此但願本文可以幫助到你們。前端

  在文章開始,我先明確幾個概念,這裏若是你以爲很差理解,就先緊緊地記住它,而後繼續往下閱讀,讀完你就會豁然開朗,相信我!另外,必定要每行每字去讀,勿跳着讀,博主就犯過這樣的錯誤,致使越讀越糊塗,我這裏也儘可能壓縮字數,保證你讀的每一個字都是有用的。答:「你都忽悠半天了趕忙開始吧!」java

  • prototype :每一個函數都會有這個屬性,這裏強調,是函數,普通對象是沒有這個屬性的(這裏爲何說普通對象呢,由於JS裏面,一切皆爲對象,因此這裏的普通對象不包括函數對象)。它是構造函數的原型對象;
  • __proto__ :每一個對象都有這個屬性,,這裏強調,是對象,一樣,由於函數也是對象,因此函數也有這個屬性。它指向構造函數的原型對象;
  • constructor :這是原型對象上的一個指向構造函數的屬性。

先看代碼函數

// Pig的構造函數
function Pig(name, age) {
    this.name = name;
    this.age = age;
}
// 建立一個Pig的實例,小豬佩奇
var Peppa = new Pig('Peppa', 5);
複製代碼

敲黑板,劃重點,理解這一句整個問題的關鍵,請多重複幾遍。:在實例化的時候,prototype上的屬性會做爲原型對象賦值給實例。 也就是說小豬佩奇的原型,就是從Pig.prototype繼承來的寫成代碼就是這個樣子Peppa.__proto__ === Pig.prototypethis

Pig是一個函數對象,它是Function對象的一個實例,因此 Pig.__proto__ === Function.prototype必定爲true。

咱們在上面提到了constructor這個屬性,它位於原型對象上而且指向構造函數,因此 Pig.prototype.constructor === Pig

至此,我大體捋了一遍這三個屬性的關係,咱們再順着這條鏈繼續往深挖一挖。 Function.prototype,也就是Function的原型對象。這個原型對象的__proto__指向了 Object.prototype。打破砂鍋問到底, Object.prototype.__proto__又指向誰,JS世界裏萬物皆對象,Object彷佛已經到了原型鏈的頂端,果真不出我所料,它確實是null。:

你可能要吐槽了,說好的講明白呢,這一坨都被你繞糊塗了,一張圖賽過千言萬語:

解釋一下上面的圖。先看藍色那條線,Pig,Function和Object的構造函數是Function的實例,因此它們的__proto__均指向Function.prototype。這就印證了敲黑板說的那句話,prototype屬性會做爲原型對象賦值給實例,每一個對象的__proto__都指向原型對象(處於最頂層的Object.prototype除外)。spa

再看綠色那條,Pig和Function的原型對象是Object的實例,因此它們的__proto__均指向了Object.prototype,也就是Object的原型對象。prototype

淺藍色的線代表了原型的constructor指向了構造函數。3d

Emmmm,其實也沒那麼複雜對不對?接着說一下原型鏈。正如你在上面圖中所看到的,JS在建立對象的時候,會在新對象上產生一個__proto__的屬性,這個屬性指向了它構造函數的原型的prototype。由此一級一級向上直到到達Object.prototype.proto === null的這個鏈條咱們稱之爲原型鏈。code

關於繼承的概念,原本想寫在一塊兒的,後來想一想,內容過多隻會讓文章成爲收藏不看系列,因此這塊的內容放在之後的文章裏詳解。各位看官,我想我大體講明白了原型和原型鏈的概念,有什麼錯誤還懇請批評指正。cdn

相關文章
相關標籤/搜索