在for循环中closures

循环中的闭合造成我的问题。 我想我必须做另一个函数返回一个函数来解决这个问题,但我不能让它与我的jQuery代码一起工作。

这是一个简单的基本问题:

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

自然地,点击三个button中的任何一个都会给出一个警告。3.我想要的function是点击button1将会发出警告,说1,button2会说2。

我怎样才能做到这一点?

看到绑定方法。

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

从文档:

可选的eventData参数不常用。 提供时,这个参数允许我们传递额外的信息给处理程序。 这个参数的一个方便的用法是解决闭包引起的问题

试试这个代码:

 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是function范围的。 如果你想要一个新的('更深')范围,你需要创build一个函数来保存它。
  • 这个解决scheme是Javascript特定的,它可以使用或不使用jQuery。
  • 这个解决scheme是有效的,因为i每个值都被复制到一个新的作用域中,并且从funMaker返回的函数在k周围closures(不会在循环中改变),而不是在i周围。
  • 你的代码不起作用,因为你传递给click函数不是“拥有” i ,它closures了创build者的i ,而且i改变了循环。
  • 这个例子可能是用funMaker内联编写的,但我通常使用这样的辅助函数来使事情更清晰。
  • funMaker的参数是k ,但这没什么区别,它可能是i没有任何问题,因为它存在于函数funMaker的范围中。
  • “环境”评估模型最清晰的解释之一是Sussman&Abelson的“计算机程序的结构和解释”( http://mitpress.mit.edu/sicp/全文在线提供,不是一个简单的阅读); – 见3.2节。 由于JavaScript实际上是C语言的Scheme,所以这个解释是可以的。

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

@Andy解决scheme是最好的。 但是,您也可以使用Javascript范围来帮助您保存closures中的值。

您可以通过执行匿名函数在循环体中创build一个新的作用域。

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

由于循环体在每次迭代中都是一个新的范围,所以在每次迭代时,索引variables都会以正确的值复制。

使用jquery中的.each函数 – 我想你是通过类似的元素循环 – 所以添加点击使用类似:

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

没有testing,但我总是在可能的情况下使用这种结构。

或者只是制造一个新的function,如你所描述的。 它看起来像这样:

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

我很确定Mehrdad的解决scheme不起作用。 当你看到人们复制到一个临时variables时,通常会保存“this”的值,这在内部子范围内可能是不同的。