【问题标题】:Javascript loop reference [duplicate]Javascript循环参考[重复]
【发布时间】:2012-07-24 15:37:04
【问题描述】:

可能重复:
javascript for loop unexpected behaviour

我在 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

但它保留了正确数量的结果..

【问题讨论】:

  • 两件事:1.您引用的代码没有这样做(您在问题的简化中丢失了一些东西 - 很容易做到!),以及 2. JavaScript 没有任何形式的传递参考。所有参数都由 value 传递。对象(包括函数)是通过引用来引用的,与“通过引用”无关。

标签: javascript node.js loops


【解决方案1】:

您引用的代码没有按照您列出的那样做,您可能丢失了一些简化问题的东西。

不过,此代码会产生您所描述的效果:

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

请注意,现在我正在创建一个函数(doSomething 所做的任何回调),而不仅仅是调用一个。

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

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

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]));
}

更多关于闭包的信息:

【讨论】:

    【解决方案2】:

    这样做:-

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

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

    【讨论】:

    • 我们不知道在他没有引用的代码上方没有var j;,也不知道(如果没有) j 曾经用于其他任何事情(例如,它可能是一个隐含的全局变量,而实际上并不是问题)。将j 设置为所引用的内容需要一段非常具体的看不见的代码。奥卡姆剃刀说……没那么多。
    【解决方案3】:

    我发现如果我使用 变量 j = 0

    for(i in groups){
    j = i
    

    系统确实可以工作,但它不是最好的遮阳篷

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多