1

可能重复:
循环内的 Javascript 闭包 - 简单的实际示例

我将举一个例子,而不是解释这个问题:

for (var i = 0; i < 100; i ++) {
  get_node(i).onclick = function() {
    do_something_very_important(i);
  }
}

有没有办法在创建而不是执行时将 i 的值替换为函数?谢谢。

4

2 回答 2

1

是的,您可以,但这不适用于您提供的示例。在那个循环中你会遇到一个非常常见的闭包问题。for

封闭在闭包中的变量共享相同的单一环境,因此在onclick调用回调时,for循环将运行,并且i变量将指向它分配的最后一个值。在您的示例中,该do_something_very_important()函数将传递100每个节点的值,这不是您想要的。

您可以使用函数工厂通过更多闭包来解决此问题:

function makeClickHandler(i) {  
  return function() {  
    do_something_very_important(i);
  };  
}

// ...

for(var i = 0; i < 100; i++) {
  get_node(i).onclick = makeClickHandler(i);
}

如果您不熟悉闭包的工作原理,这可能是一个非常棘手的话题。您可能需要查看以下 Mozilla 文章以获得简要介绍:


更新:

您还可以像@adamse 在另一个答案中建议的那样内联上述函数工厂。这实际上是一种更常见的方法,但实际上与上述相同:

for(var i = 0; i < 100; i++) {
  get_node(i).onclick = (function(p) {
    return function () {
      // we could have used i as a parameter variable as well,
      // but we're using p to better illustrate what's happening
      do_something_very_important(p); 
    }
  })(i);
}

任何另一种解决方案是通过使用自调用匿名函数将每个迭代包含在自己的范围内:

for(var i = 0; i < 100; i++) {
  (function (p) {
    // we now have a separate closure environment for each
    // iteration of the loop
    get_node(i).onclick = function() {
      do_something_very_important(p);
    }
  })(i);
}
于 2010-09-05T17:07:32.060 回答
0

是的,这有效...

for (var i = 0; i < 100; i++) {
  get_node(i).onclick = (function(i) {
    return function () {
      do_something_very_important(i);
    }
  })(i);
}
于 2010-09-05T17:11:10.010 回答