Javascript JS:哪些/如何在闭包中存储变量?

Javascript JS:哪些/如何在闭包中存储变量?,javascript,node.js,closures,Javascript,Node.js,Closures,考虑以下代码: var a = [ { a: 'I' }, { a: 'II' }, { a: 'III' } ]; for( var i=0; i<a.length; i++ ){ var j = i; var x = a[ i ]; x.bb = function(){ x.b = "-" + x.a + "-"; }

考虑以下代码:

    var a = [ { a: 'I' }, { a: 'II' }, { a: 'III' } ];

    for( var i=0; i<a.length; i++ ){

            var j = i;
            var x = a[ i ];

            x.bb = function(){
                    x.b = "-" + x.a + "-";
            }
            x.cc = function(){
                    a[ i ].c = "-" + a[ i ].a + "-";
            }
            x.dd = function(){
                    a[ j ].d = "-" + a[ j ].a + "-";
            }
    }

    for( var i=0; i<a.length; i++ ){
            a[i].bb();
            a[i].cc();
            a[i].dd();
    }

    console.log( a );
所以只有cc()完成了我想要做的事情

我现在的问题是:

  • 这里的规则是什么?变量如何存储在闭包中。(显然,
    i
    被存储为常量,
    j
    x
    被存储为对局部变量的引用,这些局部变量在for循环迭代时被更改。但这是为什么?这是我的错误。该代码之所以有效,是因为第二个和第一个
    i
    相同
  • 有没有一种写入
    bb()
    的方法,它可以存储对
    a[i]
    的引用,这样我就不必使用索引了

  • 谢谢

    您需要记住,JavaScript没有块作用域(无论如何,现在还没有),相反,一切都在“函数”级别。也就是说,所有变量的作用域都是其最新的函数定义

    变量是使用
    var
    语句声明的,根据您的代码,您拥有的每个变量的作用域都是此代码的外部容器。换句话说,如果此代码位于节点模块中,则此处的所有变量的作用域都是整个模块。因此,尽管在
    for
    循环中定义的函数都是闭包(因为所有JS函数都是闭包),但它们仍然只是使用模块中定义的变量,因为JS不需要进一步查看

    为了说明问题1的答案,请考虑以下内容:

    var o = {};
    var x = 1;
    
    function foo() {
        var x = 2;
        o.bar = function() {
            console.log(x);
        }
    }
    
    o.bar(); // will output "2" because of the closure created in `foo()`
    

    至于你的第二个问题,因为a[i]是一个对象,所以你分配给该对象的任何变量(在本例中,
    x
    )都将是一个引用,所有引用都将指向内存中的同一个对象。我不是您试图用
    bb()
    实现的目标,而是您使用
    x
    来“存储对[I]的引用”。也许你有一个更具体的例子?

    这里没有闭包。很抱歉,用错了词。那么,您如何命名这些存储对周围作用域的引用的函数呢?闭包通过保存对外部变量环境的引用来工作。在这种情况下,所有函数都具有相同的外部变量环境(即全局范围)。因此,当您在函数中引用
    i
    j
    时,您指的是存在于函数外部的全局
    i
    j
    。如果您想要捕获一个值,而不是一个(可能变化的)变量的引用,请参阅a-h。真正让我困惑的是,它似乎与
    i
    一起工作。但现在我注意到,我的第一个
    I
    和第二个
    I
    是一样的(我希望一些理智的解释器会抱怨第二个
    var
    ),在第二个循环中使用另一个变量会导致失败。@Scheintod仅供参考,重复的
    var
    语句是明确允许的(或者是允许忽略的)在ES5规范中,.@apsillers提出了一个很好的观点,这就是为什么您应该始终在JavaScript中使用它,这将迫使解释器将重复的
    var
    语句作为错误(应该是这样的)!这很简单,只需将
    “use strict;”“
    放在函数/模块的顶部即可。
    var o = {};
    var x = 1;
    
    function foo() {
        var x = 2;
        o.bar = function() {
            console.log(x);
        }
    }
    
    o.bar(); // will output "2" because of the closure created in `foo()`