JavaScript:您可以在创建时将变量替换为匿名函数吗?

时间:2010-09-05 17:02:29

标签: javascript variables function anonymous substitution

  

可能重复:
  Javascript closure inside loops - simple practical example

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

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

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

2 个答案:

答案 0 :(得分:1)

是的,你可以,但这对你提供的例子不起作用。您将在for循环中获得a very common closure problem

封闭在闭包中的变量共享相同的单个环境,因此在调用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 suggested in the other answer。这实际上是一种更常见的方法,但实际上与上述方法相同:

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

答案 1 :(得分:0)

是的,这有效......

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