昨天QT給我的一個功能提了一個bug。大概意思就是說,一段在不同位置都會被調用的代碼,在A處被調用的時候,似乎會對其他調用的地方產生影響。
我仔細debug了半天,終於找到了原因。簡化過的代碼如下:
1 function C(name, id){ 2 this.name = name; 3 var privateId = id; 4 if (typeof this.showName != "function") { 5 C.prototype.showName = function(){ 6 console.log(this.name); 7 } 8 C.prototype.showId = function(){ 9 console.log(privateId); 10 } 11 } 12 13 } 14 15 var c1 = new C('name1', 'id1'); 16 var c2 = new C('name2', 'id2'); 17 18 c1.showName(); //name1 19 c1.showId(); //id1 20 c2.showName(); //name2 21 c2.showId(); //id1 !!!!
問題出在最后一行,c2的showId方法打印出了id1。
苦思冥想良久,終於讓我想到了問題的原因——c2對象在調用構造函數的時候,不會進入if分支里面!
為什么呢?因為c1在實例化的時候,this.showName = undefined,於是進入if分支,給自己的prototype加上了一個showName方法一個showId方法。
等到c2對象實例化的時候,this.showName已經不再是undefined了,於是不會進入if分支。
這樣,c2的showId方法和c1的showId方法是同一個方法,而且這個方法里面打印的privateId變量則都是c1在實例化的時候創建的那個變量,也就是id1。
所以效果就是,本來想把privateId變量申明成一個私有變量,但這樣寫了之后,它變成了一個static變量了,真是緣木求魚,南轅北轍啊。
問題原因找到了,那么如何求解呢?
我的思路是,要使用閉包實現私有變量,那么這個閉包的函數就要與需要隱藏的變量綁定起來。而私有變量又是和類的實例綁定的,也就是c1和c2分別有自己的私有變量,所以閉包函數也必須和類的實例一一綁定。於是就改成了這樣:
1 function C(name, id){ 2 this.name = name; 3 var privateId = id; 4 if (typeof this.showName != "function") { 5 C.prototype.showName = function(){ 6 console.log(this.name); 7 } 8 9 } 10 11 this.showId = function(){ 12 console.log(privateId); 13 } 14 }
經測試,結果是正確的。
不過我依然在懷疑,我上面說的思路中“閉包的函數就要與需要隱藏的變量綁定起來”這一句,是否是正確的?如果是否,那么還有沒有其他的更好的方式實現這個需求呢?
如需轉載,請注明轉自:http://www.cnblogs.com/silenttiger/p/3443375.html
歡迎關注我的微信公眾號:老虎的小窩
