[JS必知必會]原型鏈這麼看好像並不難

對象着手

在談原型鏈以前,先了解對象。

  • 全部引用類型(函數,數組,對象)都擁有__proto__屬性(隱式原型)web

  • 全部函數擁有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;post

//調用 obj.x;//1 obj.y;//2學習

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 複製代碼

代碼簡單分析

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

代碼對象原型鏈圖:

原型鏈分析圖
原型鏈分析圖

對象訪問屬性順序

對象訪問屬性的順序,是採用向上查找,若是當前對象沒有,它會一直向上原型鏈中查找,一直找到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。

誤區

寫這篇總結的過程當中,發現不少文章都寫了「JS中萬物皆對象」。難道真的是這樣嗎? JS世界很大,並不僅有對象!推薦你們看這篇文章

常被面試官問數據類型知識你真的懂嗎?

再來看到底JS中萬物皆對象是否正確 ,是否是還有許多其餘類型。

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

相關文章
相關標籤/搜索