-1

可能重复:
javascript for 循环意外行为

我在 node.js 中编程,我遇到了一个小问题,这是由一些奇怪的引用传递问题引起的。

我使用以下代码:

for(j in groups){
  console.log(j, somefunction(groups[j]))
}

在函数内部,一些时髦的事情是用数据完成的,但之后我得到以下结果:

3 data
3 data
3 data
3 data
3 data
3 data

代替

1 data
2 data
3 data
4 data
5 data
6 data

但它保持正确数量的结果..

4

3 回答 3

1

您引用的代码没有执行您列出的操作,您可能丢失了一些简化问题的内容。

但是,此代码将具有您所描述的效果:

for(j in groups){
  doSomething(function() {
    // Callback for `doSomething`
    console.log(j, somefunction(groups[j]));
  });
}

请注意,现在我正在创建一个函数(无论doSomething做什么都是回调),而不仅仅是调用一个。

发生这种情况的原因是正在创建的函数具有对变量(以及执行上下文中的所有其他内容)的持久引用,而不是创建函数时的副本。它被称为对该执行上下文的闭包。所以你的循环运行,一系列调用开始一系列事情,然后当回调被调用时,是3,所以它们都是一样的。jdoSomethingj

通常的解决方案是创建函数来关闭在调用之前不会更改的内容,如下所示:

for(j in groups){
  doSomething(makeCallback(j));
}

function makeCallback(jarg) {
    return function() {
        console.log(jarg, somefunction(groups[jarg]));
    };
}

现在,我们jarg在回调中使用,而不是j. 因为jarg它是调用上下文的一部分makeCallback,所以它在我们创建函数和稍后调用它之间不会改变。

将数据绑定到函数的另一种方法是使用Function#bind有效地在后台创建闭包),这是 NodeJS 中可用的 ES5 功能,因为 V8 引擎具有它。看起来是这样的:

for(j in groups){
  doSomething(function(jarg) {
    // Callback for `doSomething`
    console.log(jarg, somefunction(groups[jarg]));
  }.bind(this, j)); // <== Note the bind
}

或不那么令人困惑(并且很可能更有效):

for(j in groups){
  doSomething(handler.bind(this, j));
}

function handler(jarg) {
  // Callback for `doSomething`
  console.log(jarg, somefunction(groups[jarg]));
}

更多关于闭包:

于 2012-07-24T15:49:09.343 回答
0

我发现如果我使用 var j = 0

for(i in groups){
j = i

该系统确实如何工作,但它不是最好的遮阳篷

于 2012-07-24T15:37:04.353 回答
0

这样做: -

    for(var j 分组)
    {
        //你的代码
    }

j 没有返回正确的值,因为您已在全局范围内分配了 j。希望这有帮助!

于 2012-07-24T16:37:16.457 回答