在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”的值,这在内部子范围内可能是不同的。