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:
(如發現理解錯誤指出,歡迎批評指正,相互學習)