Rob*_*Rob 12 javascript jquery closures loops
循环中的闭包导致我出现问题.我想我必须创建另一个函数来返回一个函数来解决问题,但我无法使用我的jQuery代码.
以下是简化形式的基本问题:
function foo(val) {
alert(val);
}
for (var i = 0; i < 3; i++) {
$('#button'+i).click(function(){
foo(i);
});
}
Run Code Online (Sandbox Code Playgroud)
自然地点击三个按钮中的任何一个都会发出警告说3.我想要的功能是点击按钮1将发出警告说1,按钮2会说2等.
我该怎么做呢?
And*_*y E 10
请参阅绑定方法.
$('#button'+i).bind('click', {button: i}, function(event) {
foo(event.data.button);
});
Run Code Online (Sandbox Code Playgroud)
来自文档:
可选的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));
}
Run Code Online (Sandbox Code Playgroud)
这里有一些重点:
i被复制到一个新的作用域中k,并且返回的函数funMaker关闭k(在循环中不会改变),而不是围绕i(确实如此).click函数不"拥有"它i,它关闭i它的创建者,并且i在循环中发生变化.funMaker内联编写,但我通常使用这样的帮助函数来使事情更清晰.funMakeris 的论证是k,但没有区别,它本来i没有任何问题,因为它存在于函数的范围内funMaker.编辑:修正了一些标点符号.
@Andy解决方案是最好的.但您也可以使用Javascript作用域来帮助您保存闭包中的值.
您可以通过执行匿名函数在循环体中创建新范围来实现.
for (var i = 0; i < 3; i++) {
(function(){
var index = i;
$('#button'+index).click(function(){
foo(index);
});
})();
}
Run Code Online (Sandbox Code Playgroud)
由于循环体在每次迭代时都是一个新的范围,因此索引变量在每次迭代时都会以正确的值复制.