Javascript闭包-有什么负面影响?

Javascript闭包-有什么负面影响?,javascript,closures,Javascript,Closures,问题: 闭包似乎有很多好处,但有什么坏处(内存泄漏?混淆问题?带宽增加?)?此外,我对闭包的理解正确吗?最后,一旦创建了闭包,它们可以被销毁吗 我已经读了一些关于Javascript闭包的文章。我希望有一个稍有见识的人来指导我的主张,纠正我的错误 闭包的好处: 使用内部函数将变量封装到局部范围。 函数的匿名性无关紧要 我发现有帮助的是做一些关于本地/全局范围的基本测试: <script type="text/javascript"> var global_text = ""

问题: 闭包似乎有很多好处,但有什么坏处(内存泄漏?混淆问题?带宽增加?)?此外,我对闭包的理解正确吗?最后,一旦创建了闭包,它们可以被销毁吗

我已经读了一些关于Javascript闭包的文章。我希望有一个稍有见识的人来指导我的主张,纠正我的错误

闭包的好处:

  • 使用内部函数将变量封装到局部范围。 函数的匿名性无关紧要
  • 我发现有帮助的是做一些关于本地/全局范围的基本测试:

    <script type="text/javascript">
    
       var global_text  = "";
       var global_count = 0;
       var global_num1  = 10;
       var global_num2  = 20;
       var global_num3  = 30;
    
       function outerFunc() {
    
          var local_count = local_count || 0;
    
          alert("global_num1: " + global_num1);    // global_num1: undefined
          var global_num1  = global_num1 || 0;
          alert("global_num1: " + global_num1);    // global_num1: 0
    
          alert("global_num2: " + global_num2);    // global_num2: 20
          global_num2  = global_num2 || 0;         // (notice) no definition with 'var'
          alert("global_num2: " + global_num2);    // global_num2: 20
          global_num2  = 0;
    
          alert("local_count: " + local_count);    // local_count: 0
    
          function output() {
             global_num3++;
    
             alert("local_count:  " + local_count  + "\n" +
                   "global_count: " + global_count + "\n" +
                   "global_text:  " + global_text
                  );
    
             local_count++; 
          }
    
          local_count++;
          global_count++;
    
          return output;  
       }  
    
       var myFunc = outerFunc();
    
       myFunc();
          /* Outputs:
           **********************
           * local_count:  1
           * global_count: 1
           * global_text: 
           **********************/
    
       global_text = "global";
       myFunc();
          /* Outputs:
           **********************
           * local_count:  2
           * global_count: 1
           * global_text:  global
           **********************/
    
       var local_count = 100;
       myFunc();
          /* Outputs:
           **********************
           * local_count:  3
           * global_count: 1
           * global_text:  global
           **********************/
    
    
       alert("global_num1: " + global_num1);      // global_num1: 10
       alert("global_num2: " + global_num2);      // global_num2: 0
       alert("global_num3: " + global_num3);      // global_num3: 33
    
    </script>
    
    
    var global_text=“”;
    var全局计数=0;
    var global_num1=10;
    var global_num2=20;
    var global_num3=30;
    函数outerFunc(){
    var local_count=local_count | 0;
    警报(“global_num1:+global_num1);//global_num1:未定义
    var global_num1=global_num1 | 0;
    警报(“全局num1:+global num1);//全局num1:0
    警报(“全局num2:+global num2);//全局num2:20
    global_num2=global_num2 | | 0;/(注意)没有带“var”的定义
    警报(“全局num2:+global num2);//全局num2:20
    全局μnum2=0;
    警报(“本地计数:+local计数);//本地计数:0
    函数输出(){
    全局_num3++;
    警报(“本地\u计数:“+local\u计数+”\n”+
    全局计数:“+全局计数+”\n+
    “全局文本:“+全局文本”
    );
    本地_计数++;
    }
    本地_计数++;
    全局_计数++;
    返回输出;
    }  
    var myFunc=outerFunc();
    myFunc();
    /*产出:
    **********************
    *本地人口:1
    *全球人口总数:1
    *全局文本:
    **********************/
    全局\ u text=“全局”;
    myFunc();
    /*产出:
    **********************
    *本地人口:2
    *全球人口总数:1
    *全局文本:全局
    **********************/
    var局部计数=100;
    myFunc();
    /*产出:
    **********************
    *本地人口:3
    *全球人口总数:1
    *全局文本:全局
    **********************/
    警报(“全局num1:+全局num1);//全球数字1:10
    警报(“全局num2:+全局num2);//全球人口:0
    警报(“全局num3:+全局num3);//全球人口:33
    
    我从中得到了一些有趣的东西:

  • outerFunc中的警报只调用一次,即当outerFunc调用分配给myFunc(myFunc=outerFunc())时。这个赋值似乎使outerFunc保持打开状态,我称之为持久状态

  • 每次调用myFunc时,都会执行返回。在这种情况下,返回是内部函数

  • 真正有趣的是定义局部变量时发生的本地化。请注意,在第一个警报中,global_num1和global_num2之间存在差异,即使在尝试创建变量之前,global_num1也被认为是未定义的,因为“var”用于表示该函数的局部变量。-这在之前已经讨论过了,按照Javascript引擎的操作顺序,很高兴看到它开始工作

  • 全局变量仍然可以使用,但局部变量将覆盖它们。请注意,在第三次myFunc调用之前,创建了一个名为local_count的全局变量,但它对内部函数没有影响,该函数有一个同名变量。相反,正如global_var3所注意到的,每个函数调用都有修改全局变量的能力

  • 发布想法: 尽管代码很简单,但对你们来说,它会被警报弄得乱七八糟,所以你们可以即插即用

    我知道还有其他闭包的例子,其中许多闭包使用匿名函数和循环结构,但我认为这对于101入门课程来说是一个很好的例子

    我关心的一件事是闭包对内存的负面影响。因为它保持函数环境的开放性,所以它也将这些变量存储在内存中,这可能/可能不会影响性能,特别是在DOM遍历和垃圾收集方面。我也不确定这将在内存泄漏方面扮演什么样的角色,也不确定是否可以通过简单的“delete myFunc;”从内存中删除闭包

    希望这对别人有帮助


    vol7ron

    你可能会得到一大堆好答案。一个肯定的负面因素是Internet Explorer循环引用内存泄漏。基本上,JScript不认为DOM对象的“循环”引用是可收集的。使用闭包很容易创建IE认为的循环引用。第二个链接中提供了几个示例

    在IE6中,回收内存的唯一方法是终止整个进程。在IE7中,他们对其进行了改进,这样当您离开(或关闭)有问题的页面时,内存就会被回收。在IE8中,JScript可以更好地理解DOM对象,并按照您预期的方式收集它们


    IE6的建议解决方法(除了终止进程!)是不要使用闭包。

    闭包可能会导致内存泄漏,但Mozilla已尝试优化其垃圾收集引擎以防止这种情况

    我不确定Chrome如何处理闭包。我认为它们和Mozilla相当,但我不想肯定。IE8显然比IE的早期版本有所改进——它几乎是一款全新的浏览器,但仍有一些细微差别


    您还应该对代码进行基准测试,看看在速度方面是否有任何改进。

    闭包带来了很多好处……但也带来了一些好处
    function ScopeIssues(count) {
        var funcs = [];
        for (var i = 0; i < count; ++i) {
            funcs[i] = function() { console.log(i); }
        }
        return funcs;
    }
    
    x = ScopeIssues(10);
    
    x[0]();   // outputs 10
    x[1]();   // does too
    x[2]();   // same here
    x[3]();   // guess
    
    function Corrected(count) {
        var funcs = [];
        for (var i = 0; i < count; ++i) {
            (function(which) {
                funcs[i] = function() { console.log(which); };
            })(i);
        }
        return funcs;
    }
    
    x = Corrected(10);
    
    x[0]();  // outputs 0
    x[1]();  // outputs 1
    x[2]();  // outputs 2
    x[3]();  // outputs 3
    
    function WorksToo(count) {
        var funcs = [];
        for (let i = 0; i < count; ++i) {
            funcs[i] = function() { console.log(i); }
        }
        return funcs;
    }
    
    x = WorksToo(10);
    
    x[0]();  // outputs 0
    x[1]();  // outputs 1
    x[2]();  // outputs 2
    x[3]();  // outputs 3
    
    value = 'global variable';
    
    function A() {
        var value = 'local variable';
        this.value = 'instance variable';
        (function() { console.log(this.value); })();
    }
    
    a = new A();  // outputs 'global variable'
    
    function A() {
        var self = this;
        this.value = 'some value';
        (function() { console.log(self.value); })();
    }
    
    function X() {
        var self = this;
        var Y = function() {
            var outer = self;
            var self = this;
        };
    }
    
    function X() {
        var self, Y;
        self = this;
        Y = function() {
            var outer, self;
            outer = self;
            self = this;
        };
    }