js 原型鏈

記錄下本身對js 原型的一些理解
先看一下什麼是 ····原型鏈數組

function Foo(){}
Foo.prototype.num = 3;
// new Foo( ) 將返回一個對象 把這個對象賦值給了 bar 
var bar = new Foo();
// bar 是怎麼找到的原型下面的num呢?
alert(bar.num); //3

bar並無num 屬性,它是怎麼拿到3的呢 此處的 bar 就是經過原型鏈找到了值
原型鏈
JavaScript中的對象有一個特殊的 __proto__ 內置屬性,其實就是對於其餘對象的引用(關聯)。當咱們使用 function關鍵字聲明一個函數時,系統會自動建立一個對象,訪問這個對象能夠經過 函數名.prototype 訪問(咱們通常把這個對象叫作原型對象),當使用 new 關鍵字調用函數(這時咱們通常把這個函數稱爲構造函數)時其中有一個步驟就是對建立的對象進行原型關聯,關聯到聲明函數時建立的那個對象(函數名.prototype指向的那個對象)函數

上面例子 中使用 new 關鍵字調用 Foo()函數時會建立一個對象咱們把這個對象賦值給了 bar ; bar對象內部的.__proto__屬性會關聯到聲明函數時建立的那個對象(Foo.prototype) , bar.num屬性在bar中沒法找到時,就會訪問bar.__proto__查找,這個過程會持續到找到匹配的屬性名或者查找完整條prototype鏈(全部普通的[[Prototype]]鏈最終都會指向內置的Object.prototype)
,所以上面例子的原型鏈是這樣的this

bar.__proto__ -- 指向 --> Foo.prototype --而後(Foo.prototype.__proto__) -- 指向 --> Object.prototype

所以
每一個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。那麼,假如咱們讓原型對象等於另外一個類型的實例,結果會怎麼樣呢?顯然,此時的原型對象將包含一個指向另外一個原型的指針,相應地,另外一個原型中也包含着一個指向另外一個構造函數的指針。假如另外一個原型又是另外一個類型的實例,那麼上述關係依然成立,如此層層遞進,就構成了實例與原型的鏈條。這就是所謂原型鏈的基本概念
對prototype更詳細的介紹請看這裏(https://developer.mozilla.org...prototype

原型鏈的問題

包含引用類型值的原型屬性會被全部實例共享;(而這也正是爲何要在構造函數中,而不是在原型對象中定義屬性的緣由)在經過原型來實現繼承時,原型實際上會變成另外一個類型的實例。因而,原先的實例屬性也就瓜熟蒂落地變成了如今的原型屬性了。下列代碼能夠用來講明這個問題。指針

function SuperType(){   
  this.colors = ["red", "blue", "green"];
}
function SubType(){}//繼承了SuperType
SubType.prototype = new SuperType();
var instance1 =newSubType();
instance1.colors.push("black");
//"red,blue,green,black"
alert(instance1.colors);
var instance2 = new SubType();
//"red,blue,green,black"
alert(instance2.colors);

SuperType構造函數定義了一個colors屬性,該屬性包含一個數組(引用類型值)。SuperType的每一個實例都會有各自包含本身數組的colors屬性。當SubType經過原型鏈繼承了SuperType以後,SubType.prototype就變成了SuperType的一個實例,所以它也擁有了一個它本身的colors屬性——就跟專門建立了一個SubType.prototype.colors屬性同樣。但結果是什麼呢?結果是SubType的全部實例都會共享這一個colors屬性。而咱們對instance1.colors的修改可以經過instance2.colors反映出來,就已經充分證明了這一點。code

在建立子類型的實例時,不能向超類型的構造函數中傳遞參數。實際上,應該說是沒有辦法在不影響全部對象實例的狀況下,給超類型的構造函數傳遞參數。有鑑於此,再加上前面剛剛討論過的因爲原型中包含引用類型值所帶來的問題,實踐中不多會單獨使用原型鏈對象

相關文章
相關標籤/搜索