javascript典型bug——錯誤的閉包


昨天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 

 

歡迎關注我的微信公眾號:老虎的小窩
微信公眾號 老虎的小窩


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM