JS中的原型和原型鏈

為什么要理解原型和原型鏈,因?yàn)橛欣谖覀兝斫夂蛯?shí)現(xiàn) JS對(duì)象繼承。

__proto__

  • __proto__是什么

    When a constructor creates an object, that object implicitly references the constructor’s prototype property for the purpose of resolving property references. -----------ES6 文檔

    JS 中創(chuàng)建出來的對(duì)象都會(huì)有一個(gè)隱式引用,它指向的是構(gòu)造器的prototype。這個(gè)隱式引用就是對(duì)象內(nèi)部[[prototype]],通常情況下我們是無法訪問到這個(gè)屬性的,但是可以通過瀏覽器實(shí)現(xiàn)的 __proto__ 屬性去訪問它,每一個(gè)對(duì)象都會(huì)有一個(gè)__proto__屬性。雖然可以通過__proto__ 訪問到[[prototype]],但是ECMAScript 不建議通過__proto__ 去修改內(nèi)部[[prototype]] 屬性,因?yàn)檫@是個(gè)影響性能的操作。

  • __proto__指向哪里
    __proto__ 是一個(gè)引用而且指向constructor 的prototype

zhg
zhg

prototype

  • prototype 是什么?
    只有函數(shù)才會(huì)有prototype 屬性。當(dāng)你創(chuàng)建一個(gè)函數(shù)時(shí),它的prototype會(huì)初始化為一個(gè)"空對(duì)象" (里面含有一個(gè)constructor屬性,它是不可枚舉屬性,近似認(rèn)為"空對(duì)象"),之后就可以往里面增加屬性或方法。prototype主要用于存儲(chǔ)公用的方法和屬性,然后等待實(shí)例的__proto__ 來指向它。

    zhg
    zhg

原型鏈

  • 空對(duì)象toString() 方法從何而來?

    zhg

    其實(shí)上面的代碼,做了下面幾件事:

    1. 看看 obj 對(duì)象本身有沒有 toString 屬性。沒有就走到下一步。
    2. 看看 obj.__proto__ 對(duì)象有沒有 toString 屬性,發(fā)現(xiàn) obj.__proto__ 有 toString 屬性,于是找到了。所以 obj.toString 實(shí)際上就是第 2 步中找到的 obj.__proto__.toString。
      ------知乎專欄:什么是 JS 原型鏈?

    由于obj.__proto__ === Object.prototype 所以obj 還可以調(diào)用Object.prototype 中其它的屬性。可是如果obj 調(diào)用的屬性在Object.prototype 上也沒有呢?那么它就會(huì)在Object.prototype.__proto__ 中尋找,又 Object.prototype.__proto__ 等同于 obj.__proto__.__proto__。所以如果在obj.__proto__.__proto__ 上也沒有找到,他會(huì)繼續(xù)在obj.__proto__.__proto__.__proto__ 上尋找,直到他找到屬性或者 .__proto__ 為null 。

    obj.__proto__.__proto__. . . . . .這樣由.__proto__組成的鏈條,就是原型鏈。 通過原型鏈,實(shí)例可以得到自身沒有但原型鏈上存在的方法或?qū)傩浴?/p>

    其實(shí)instanceof 就是利用原型鏈的特點(diǎn)來工作的。比如判斷obj 是否是Object 的實(shí)例(obj instanceof Object),相當(dāng)于判斷 obj.__proto__.__proto__. . . 是否等于Object.prototype。

  • 原型鏈的重點(diǎn)
    __proto__prototype 之間的相互關(guān)系,構(gòu)成了JS 的原型鏈。個(gè)人認(rèn)為掌握原型鏈,必須記住下面三句話:

    • 某對(duì)象的__proto__ ===== 它構(gòu)造函數(shù)的prototype
    • Object.prototype.__proto__ ===== null
    • Function.prototype.__proto__ ===== Object.prototype
  • Function.prototype 和Obect.prototype
    Function是所有函數(shù)的原型(Function.prototype除外)。它是對(duì)象同時(shí)又是函數(shù),所以它有__proto__prototype屬性。利用上面三句話的第一句某對(duì)象的proto===== 它構(gòu)造函數(shù)的prototype,可以得到:Function.__proto__ === Function.prototype。而Object、Number、StringArrayBoolean 等構(gòu)造函數(shù)情況同Function 相差不大,所以它們都是繼承自Function,它們的__proto__ 會(huì)等于 Function.prototype。

    Function.prototype 繼承自哪里?

    typeof Function.prototype  //"function"
    Function.prototype instanceof Function  //false
    Function.prototype.prototype  //undefined
    

    由上面可以得到:Function.prototype 是一個(gè)沒有prototype屬性的函數(shù),它不是繼承自Function。

    Function.prototype instanceof Object  //true
    Function.prototype.__protot__ === Object.prototype  //true
    

    得到Function.prototype 是繼承自O(shè)bject 的。
    Object.prototype繼承自哪里?

    typeof Object.prototype  //"object"
    Object.prototype instanceof Object  //false
    Object.prototype.__proto__ === null
    

    得出Object.prototype 是一個(gè)對(duì)象,但他不是繼承自Object對(duì)象,也不是繼承自null,它是對(duì)象繼承的最頂端。

  • 總結(jié)

zhg
  • 原型圖
圖片來自網(wǎng)絡(luò)

鏈接

1、proto和prototype來深入理解JS對(duì)象和原型鏈
2、js中proto和prototype的區(qū)別和關(guān)系? ---蘇墨橘的回答
3、什么是 JS 原型鏈?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容