1. 程式人生 > >javascript Prototype constructor的理解(一)

javascript Prototype constructor的理解(一)

 Prototype屬性

a)      Prototype:每一個函式都包含一個prototype屬性,這個屬性指向的是一個物件的引用;而對已每一個函式(類)的例項都會從prototype屬性指向的物件上繼承屬性,換句話說通過同一個函式建立的所有物件都繼承一個相同的物件。

b)      通過new 關鍵字和建構函式建立的物件的原型,就是建構函式的prototype指向的那個物件

下面通過一個函式可以解釋a b兩條說明的問題,程式碼如下

function A(name){
	  this.name = name;
}
var a1 = new A("aa1");
var a2 = new A("aa2");

用chrome的take heap snapshot可以看到下面的東西


                                                 圖1.2

 分析說明:如圖1.2,可以發現a1、a2物件的_proto_右邊的@後面的值都是1426796,等於Prototype物件歲代表的@1423679,所以有如下關a1.__proto__ ==== a2.__proto__=== A.prototype

   用影象直觀表示如下:


                                                                          圖 1.3

到此說明了a,b兩點是正確的。

同事上面的也可以論證一下觀點(該觀點摘自javascript權威指南):

1)  同一個類的所有例項都從同一個原型物件上繼承屬性

2)  當且僅當兩個物件繼承自同一個原型物件時,他們才是屬於同一個類的例項

特別說明:只有建構函式才有prototype屬性,而建構函式的例項是沒有該屬性的,也就是說console.log(a1.prototype)輸出的是undefined。在javascript中,每個函式都自動有一個prototype屬性,而不是每一個物件擁有prototype屬性

  原型屬性與例項物件的建立與否沒有關係,它在物件建立之前就已經存在

Constructor屬性

  觀察上圖藍色背景部分,每一個函式的Prototype屬性指向的物件都包含唯一一個不可列舉屬性constructor,該屬性的值是這麼一個物件:它指向了它所在的建構函式。

   如圖:Prototype中的constructor指向的是functionA()這個它所在的建構函式


                                                 圖   1.4

   直觀表示如下圖:

  

                                                                      圖 1.5

此時 alert(A.prototype.constructor)的結果是:

function A(name){
	  this.name = name;
}
通過上面的兩個圖,可以得到如下的結論:在Prototype屬性指向的物件中存在預先定義好的constructor屬性,每個建構函式的例項繼承了這一屬性,所以在不重寫Prototype物件的情況下,例項的constructor指向它們的建構函式

Var a = new A();

a.constructor === A// =>true

如果重寫了Prototype物件,程式碼如下:

  A.prototype = {
	  getName:function(){return this.name}
 };

此時生成的A的物件只有兩個即:a1,a2,而沒有Prototype物件,如下


問題出來了,那這個Prototype物件到哪兒去了呢?看綠色方框裡面的@81203,通過它進行查詢,在Object例項中找到了這個物件的資訊


注意:新定義Prototype物件的話,該Prototype物件原有的constructor屬性會丟失,該Prototype此時所指的物件(即{getName:function(){return this.name}}物件)的constructor就是Object,事實上{getName:function()}就是一個Object物件。相信如果A.prototype={getName:function(){returnthis.name}}換成這樣寫的話,理解起來會方便寫:

Var obj = {getName:function(){}}

A.prototype = obj;

//或者這樣寫:

Var obj = new Object();

Obj.getName = function(){

};

A.prototype = obj;

此時用圖形表示a1,a2,prototype物件的關係如下:



通過這個圖可以很直觀的看出:

a1.constructor ===  A//=>false

a1.constructor === Object//=>true

A.prototype.constructor === Object

.修改這個問題的辦法就行給重定義的Prototype物件顯式的新增一個constructor屬性,修改其constructor的指向:

  A.prototype = {
	  constructor:A,
	  getName:function(){return this.name}
 }

那麼通過chrome的Take Heap Snapshot分析得到效果圖如圖1.3:

(如發現理解錯誤指出,歡迎批評指正,相互學習)