1. 程式人生 > >徹底理解什麼是原型鏈,prototype和__proto__的區別。

徹底理解什麼是原型鏈,prototype和__proto__的區別。

1.Javascript中所有的物件都是Object的例項,並繼承Object.prototype的屬性和方法,也就是說,Object.prototype是所有物件的爸爸。(個人感覺搞清楚這一點很重要) 。

   在物件建立時,就會有一些預定義的屬性,其中定義函式的時候,這個預定義屬性就是prototype,這個prototype是一個普通的物件。

而定義普通的物件的時候,就會生成一個__proto__,這個__proto__指向的是這個物件的建構函式的prototype.

詳情請看例一:(建議大家用谷歌瀏覽器檢視這些物件的屬性);

function A(a){
		this.a = a;
	}

首先定義一個函式a,如上面所說,函式在被定義的時候就擁有了一個prototype物件。我們來列印看一下

console.log(A.prototype)

瀏覽器的結果:


如上圖,這就是函式a的prototype物件,(記住我們最開始說的,凡是物件都會有一個屬性那就是__proto__)。這個__proto__指向的就是他的建構函式的prototype 而這個函式a的prototype物件的建構函式是誰呢? 沒錯就是開頭說到的Object.prototype。

看如下程式碼:

        console.log(A.prototype.__proto__)
	console.log(Object.prototype)

而這兩個的結果如下:


打印出來是同一個東西,也就是說Object.prototype是所有函式的爹,當你宣告一個函式的時候也就是相當於對Object的例項化。這裡可以對比一下new一個例項。

我們也可以用幾個方法來驗證一下:

        console.log(Object.prototype.isPrototypeOf(A))//true
	console.log(A instanceOf Object) //true

函式a的prototype物件的另一個屬性是constructor這個屬性就指向了函式a本身,也就是指向了他自己的建構函式。

2.我們在來用一個例項物件來說明一下原型,程式碼如下:

        function B(b){
		this.b = b;
	}
	var b = new B('lc');

當我們宣告一個函式B時就自動建立了prototype物件。而b是建構函式的B的例項,這是候b是一個物件,而我們知道,物件只有__proto__屬性。而這個屬性是指向他的建構函式(B)的prototype屬性。這時候我們來列印一下b

console.log(b)

可以看到b中只有__proto__屬性,而這個屬性是指向他的建構函式的prototype物件的,也就是說

(b.__proto__==B.prototype)答案為true;

這就是js中的prototype和__proto__的區別。

那麼什麼是原型鏈呢?接著上面的講,我們都知道物件都有一個toString方法。上述的例項化物件b也可以toString,

而例項化物件b本身並沒有toString的方法,那他就會沿著它的__proto__向他的建構函式B的prototype物件去找,而這裡也沒有,那他就會 繼續沿著B.prototype.__proto__向上找。而B.prototype.__proto__指向的就是Object.prototype。

我們列印一下Object.prototype:


這就是原型鏈查詢,而則一層一層的連結 關係就是原型鏈。