for循环中的闭包

时间:2010-02-03 13:53:30

标签: javascript jquery loops closures

循环中的闭包导致我出现问题。我想我必须创建另一个函数来返回一个函数来解决问题,但我无法使用我的jQuery代码。

以下是简化形式的基本问题:

function foo(val) {
  alert(val);
}

for (var i = 0; i < 3; i++) {
  $('#button'+i).click(function(){
    foo(i);
  });
}

自然地点击三个按钮中的任何一个都会发出警告说3.我想要的功能是点击按钮1会发出一个警告说1,按钮2会说2等。

我该怎么做呢?

5 个答案:

答案 0 :(得分:10)

请参阅bind方法。

$('#button'+i).bind('click', {button: i}, function(event) {
  foo(event.data.button);
});

来自文档:

  

可选的eventData参数是   不常用。提供的时候,这个   参数允许我们传递额外的   处理程序的信息。一个方便   使用此参数是有效的   围绕由闭包引起的问题

答案 1 :(得分:6)

试试这段代码:

function foo(val) {
  alert(val);
}

var funMaker = function(k) {
  return function() {
    foo(k);
  };
};

for (var i = 0; i < 3; i++) {
  $('#button'+i).click(funMaker(i));
}

这里有一些重点:

  • JavaScript是功能范围的。如果你想要一个新的(“更深的”)范围,你需要创建一个函数来保存它。
  • 此解决方案是特定于Javascript的,无论是否使用jQuery都可以。
  • 该解决方案有效,因为i的每个值都在k的新范围内复制,而funMaker返回的函数在k附近关闭(不是i在循环中改变),而不是click(确实如此)。
  • 您的代码不起作用,因为您传递给i的函数不“拥有”i,而是关闭其{1}}的创建者,{ {1}}循环中的变化。
  • 该示例可能是用i内联编写的,但我通常使用这样的帮助函数来使事情更清晰。
  • funMaker的论点是funMaker,但没有区别,它可能是k没有任何问题,因为它存在于函数{{1}的范围内}。
  • “环境”评估模型的最清晰解释之一可在Sussman&amp; Sons的“计算机程序的结构和解释”中找到。 Abelson(http://mitpress.mit.edu/sicp/全文可在线获取,不易阅读) - 见3.2节。由于JavaScript实际上是带有C语法的Scheme,因此该解释没问题。

编辑:修正了一些标点符号。

答案 2 :(得分:5)

答案 3 :(得分:3)

使用jquery中的.each函数 - 我猜你是一个循环遍历类似的元素 - 所以使用类似的东西添加点击:

$(element).children(class).each(function(i){
   $(this).click(function(){
      foo(i);
   });
});

未经测试但我总是尽可能使用这种结构。

答案 4 :(得分:1)

或者只是制作一个新功能,正如您所描述的那样。它看起来像这样:

function foo(val) {
    return function() {
        alert(val);
    }
}

for (var i = 0; i < 3; i++) {
    $('#button'+i).click(foo(i));
}

我很确定Mehrdad的解决方案不起作用。当您看到人们复制到临时变量时,通常会保存“this”的值,这可能在内部子范围内有所不同。