javascript - JS : Which/How are variables stored in 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 + "-";
            }
            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 );

将导致(省略函数):

[ { a: 'I', c: '-I-' },
  { a: 'II', c: '-II-' },
  { a: 'III', b: '-III-', d: '-III-', c: '-III-' } ]

所以只有 cc() 能完成我想要做的事情。

我现在的问题是:

  1. 变量在闭包中存储的规则是什么。 (显然,i 存储为常量,而 jx 存储为对局部变量的引用,这些变量在 for -loop 迭代。但这是为什么呢?) 这是我的错误。该代码之所以有效,是因为第二个和第一个 i 相同!
  2. 有没有办法以存储对 a[ i ] 的引用的方式编写 bb() ,这样我就不必使用索引?

谢谢!

最佳答案

您需要记住,JavaScript 没有 block 作用域(好吧,无论如何还没有, ES6 is working that in with let ),相反,一切都在“函数”级别。也就是说,所有变量的作用域都是其最新的函数定义。

变量是使用 var 语句声明的,并且根据您的代码,您拥有的每个变量的作用域都限于此代码的外部容器。换句话说,如果这段代码位于 Node 模块中,那么这里的所有变量的作用域都是整个模块。因此,虽然在 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 来“存储对 a[ i ] 的引用”。也许你有更具体的例子?

关于javascript - JS : Which/How are variables stored in closures?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27359918/

相关文章:

循环中的 Golang 匿名函数 - 作为参数传递的值的问题

rust - Rust 中闭包参数的生命周期问题

javascript - 了解 JavaScript 中的递归异步调用

javascript - Sequelize.js setter 函数没有按我的预期工作

javascript - Div 位置不正确

javascript - 实现 JS 按钮 - 如何仅复制代码而不复制注释

node.js - 如何托管静态登陆页面并在同一 Node 服务器上使用react?

swift - 在 Swift 中调用函数并从闭包内传递参数

javascript - 在不同的 Vuex 模块中提交变更

javascript - 找不到名称“withStyles”