javascript之原型鏈詳解

對象着手

在談原型鏈以前,先了解對象,萬物皆對象。
  • 全部引用類型(函數,數組,對象)都擁有__proto__屬性(隱式原型)程序員

  • 全部函數擁有prototype屬性(顯式原型)(僅限函數)數組

  • 原型對象:擁有prototype屬性的對象,在定義函數時就被建立微信

prototype與__proto__兩個概念

  • prototype:此屬性只有構造函數纔有,它指向的是當前構造函數的原型對象。
  • proto:此屬性是任何對象在建立時都會有的一個屬性,它指向了產生當前對象的構造函數的原型對象,因爲並不是標準規定屬性,不要隨便去更改這個屬性的值,以避免破壞原型鏈,可是能夠藉助這個屬性來學習,所謂的原型鏈就是由__proto__鏈接而成的鏈。

原型鏈詳解

在js代碼中 經過對象建立(下面一段簡單的代碼)詳細分析原型鏈 一段簡單代碼:函數

code

function foo(){} foo.prototype.z=3;

var obj=new foo(); obj.y=2; obj.x=1;學習

//調用 obj.x;//1 obj.y;//2ui

obj.z;//3spa

typeof obj.toString;//'function' 'z' in obj;//true obj.hasOwnProperty('z');//falseprototype

複製代碼obj.z=5; obj.z;//5 'z' in obj;//true obj.hasOwnProperty('z');//true foo.prototype.z;//3 複製代碼

  • 代碼簡單分析cdn

    上面一段代碼,聲明第一個函數foo的時候,它就會帶一個foo.prototype的屬性,這個屬性是一個對象屬性,用new foo();構造器的方式構造一個新的對象obj。這時候這個obj的原型會指向foo的prototype屬性。 對於這個foo函數的原型也會指向Object.prototype,這個Object.prototype也是有原型的,它的原型指向null。

  • 代碼對象原型鏈圖:

原型鏈分析圖
原型鏈分析圖
  • 對象訪問屬性順序

    對象訪問屬性的順序,是採用向上查找,若是當前對象沒有,它會一直向上原型鏈中查找,一直找到null,若是尚未會返回undefind。

  • 對象中值修改說明

    代碼中修改obj.z的值後,再次輸出obj.z的時候是5,foo.prototype.z是3,說明咱們在修改或添加對象的屬性的時候,只是修改了對象自己obj.prototype.z中的值,而原型鏈中foo.prototype.z的值並不會修改。

  • in,hasOwnProperty等方法的出現

    首先查看整個原型鏈,會想這兩個方法是怎麼來的,在foo的的proto指向上一級Object.prototype的時候,就能夠訪問Object中的一些函數和屬性了,其中就包括這兩個方法。

    第一次調用

    'z' in obj;//true 
    obj.hasOwnProperty('z');//false
    複製代碼

    表示的是z並非obj這個對象上的,而是對象的原型鏈上的。

    'z' in obj;//true
      obj.hasOwnProperty('z');//true
      foo.prototype.z;//3
    複製代碼

    第二次修改了obj.z的值,z就是obj這個對象上的了,可是也並無修改原型鏈中的z的值。

特殊說明

_proto_是每個對象都有的屬性,它的指向會有一個特殊說明,大多數狀況下 _proto_指向了產生當前對象的構造函數的原型對象,也就是那個 prototype。可是會有特殊的狀況

  • 特殊狀況
var a={};
 var b=Object.create(a);
複製代碼

object.create是建立了一個空對象,空對象的原型指向a,a也是空對象,這其中不存在prototype;Object.create在繼承中也常被使用,建立一個空對象指向()內的對象,這這樣實現了b繼承a,也不會篡改a中的內容,在這裏就不具體說明了。

原理圖分析

原理圖分析
原理圖分析

總結

  • 到底什麼是原型鏈?

    proto是任何對象都有的屬性,在js中萬物皆對象,因此會造成一條proto連起來的鏈條,遞歸訪問proto必須最終到頭,而且值是null。

以爲本文對你有幫助?請分享給更多人

歡迎你們關注個人公衆號——程序員成長指北。請自行微信搜索——「程序員成長指北」

相關文章
相關標籤/搜索