javascript典型bug——錯誤的閉包

昨天QT給個人一個功能提了一個bug。大概意思就是說,一段在不一樣位置都會被調用的代碼,在A處被調用的時候,彷佛會對其餘調用的地方產生影響。javascript

我仔細debug了半天,終於找到了緣由。簡化過的代碼以下:html

 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。java

 

苦思冥想良久,終於讓我想到了問題的緣由——c2對象在調用構造函數的時候,不會進入if分支裏面!微信

爲何呢?由於c1在實例化的時候,this.showName = undefined,因而進入if分支,給本身的prototype加上了一個showName方法一個showId方法。閉包

等到c2對象實例化的時候,this.showName已經再也不是undefined了,因而不會進入if分支。函數

這樣,c2的showId方法和c1的showId方法是同一個方法,並且這個方法裏面打印的privateId變量則都是c1在實例化的時候建立的那個變量,也就是id1。測試

因此效果就是,原本想把privateId變量申明成一個私有變量,但這樣寫了以後,它變成了一個static變量了,真是緣木求魚,南轅北轍啊。this

 

問題緣由找到了,那麼如何求解呢?spa

個人思路是,要使用閉包實現私有變量,那麼這個閉包的函數就要與須要隱藏的變量綁定起來。而私有變量又是和類的實例綁定的,也就是c1和c2分別有本身的私有變量,因此閉包函數也必須和類的實例一一綁定。因而就改爲了這樣:prototype

 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 

 

歡迎關注個人微信公衆號:老虎的小窩
微信公衆號 老虎的小窩

相關文章
相關標籤/搜索