Javascript的繼承采用的是原型繼承方式,即使用某個構造函數生成的對象可以使用這個構造函數的原型對象的方法。
好了,熟悉JS的人都知道上面這個事實,下面我們來看一個詭異的問題。
先看這段代碼:
1 var ProtoTypeClazz = function(){
2 this.arr = [];
3 }
4
5 ProtoTypeClazz.prototype.add = function(){
6 this.arr.push("testData");
7 }
8
9 ProtoTypeClazz.prototype.print = function(){
10 alert(this.arr);
11 }
12
13 var Clazz = function(){}
14 Clazz.prototype = new PrototypeClazz();
15
16 var obj1 = new Clazz();
17 obj1.add();
18 obj1.print();//輸出testData
19
20 var obj2 = new Clazz();
21 obj2.add();
22 obj2.print();//輸出testData,testData
上述這個代碼熟悉JS的人都很理解,每個ProtoTypeClazz類型的對象有一個名為arr的數組變量。obj1和obj2共享一個ProtoTypeClazz類型的對象,這個對象在第14行生成。obj1和obj2的操作都是對這個對象進行操作,所以兩次add方法的效果疊加,第一次print輸出testData,第二次輸出testData,testData
那么我們來看一下下面一段代碼:
1 var ProtoTypeClazz = function(){
2 this.value = 1;
3 }
4
5 ProtoTypeClazz.prototype.add = function(){
6 this.value++;
7 }
8
9 ProtoTypeClazz.prototype.print = function(){
10 alert(this.value);
11 }
12
13 var Clazz = function(){}
14 Clazz.prototype = new PrototypeClazz();
15
16 var obj1 = new Clazz();
17 obj1.add();
18 obj1.print();//輸出2
19
20 var obj2 = new Clazz();
21 obj2.add();
22 obj2.print();//輸出2
這段代碼和上一段代碼不同的地方是,每個ProtoTypeClazz對象中保存的變量是一個名叫value的基礎類型變量。上一段代碼保存的是一個數組。
奇怪的地方來了,第二段代碼兩次的輸出都是2,而不是2和3。既然是共享同一個對象,為什么和上一段代碼返回的結果不一樣?兩次add為什么沒有累加?
很奇怪吧,兩段代碼我只是變了下變量,但結果卻不一樣,第一段代碼的結果是大家可以預計的,那第二段代碼為什么是這個結果呢?
原因是這樣的,在Javascript中,一個對象繼承自原型對象,則如果自己定義了和原型變量名字一樣的變量,則會覆蓋原型變量中的變量。
在第二段代碼中,當obj1執行add方法時,this.b++;等於this.b = this.b + 1;所以在obj1中生成了自己的b變量,並沒有修改原型對象中的b變量。而在第一段代碼中,調用的是arr數組對象的某個方法,修改的還是原來的數組對象。
這就是這段詭異代碼的原因。深入了解JS的原型機制是非常重要的。
歡迎一同學習成長,新浪微博:弈軒-TB