zoukankan      html  css  js  c++  java
  • 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 

    欢迎关注我的微信公众号:老虎的小窝
    微信公众号 老虎的小窝

  • 相关阅读:
    vtk 矩阵管理系统
    在opengl中使用纹理
    [译文]:单元测试的七种境界
    [翻译]:六分钟八法则塑造优秀程序员
    weekly review 200921: Power Sleep
    Bye, Scofield
    weekly review 200922: Goal
    weekly review 200920: Prototype Demo
    转载:测试驱动开发三原则
    weekly review 200918: productive
  • 原文地址:https://www.cnblogs.com/silenttiger/p/3443375.html
Copyright © 2011-2022 走看看