请看jsfiddle: http://jsfiddle.net/LsNCa/2/
function MyFunc() {
for (var i = 0; i < 2; i++) { // i= 0, 1
var myDiv = $('<div>');
myDiv.click(function(e) {
alert(i); // both the two divs alert "2", not 0 and 1 as I expected
});
$('body').append(myDiv);
}
}
var myFunc = new MyFunc();
当我点击它时,我希望div分别提醒“0”和“1”。但他们两个都警告“2”。
当我点击div并触发事件时,处理程序如何以及在何处找到变量i的值?
我知道添加一个闭包可以实现我的目标。但为什么呢?
答案 0 :(得分:7)
function MyFunc() {
for (var i = 0; i < 2; i++) { // i= 0, 1
(function(j) {
var myDiv = $('<div>');
myDiv.click(function(e) {
alert(j);
});
$('body').append(myDiv);
})(i);
}
}
var myFunc = new MyFunc();
上面的代码是你如何使它正常工作。没有闭包,你总是i的最后一个值。我们所做的是将i发布到闭包中,让运行时“记住”那个时刻的值。
答案 1 :(得分:2)
您需要一个闭包,因为所有事件处理函数都引用相同的变量i
。 for
循环更新此循环,当循环完成时,变量包含2
。然后当有人点击其中一个DIV时,它会访问该变量。
要解决这个问题,每个事件处理程序都需要是一个带有自己的变量i
的闭包,它包含创建闭包时值的快照。
答案 2 :(得分:1)
我建议您阅读this article
JavaScript提升声明。这意味着两个var语句 和函数声明将移动到其封闭的顶部 范围。
正如@Barmar在上面的回答中所说,变量i
被两个事件处理程序引用。
您应该避免在循环内声明函数。下面有一些代码可以满足您的需求。
我假设您正在使用jQuery。
function MyFunc() {
for (var i = 0; i < 2; i++) { // i= 0, 1
var myDiv = $('<div>');
$('body').append(myDiv);
}
$('div').on('click', function() {
alert($(this).index());
});
}
var myFunc = new MyFunc();
答案 3 :(得分:0)
在for循环完成后发生“alert()”调用,这意味着“i”的值将是之后任何内容的最后一个值。为了捕获“i”的单个值,您必须通过创建新函数为每个值创建一个闭包:
function MyFunc() {
function alertFn(val) {
return function () {
alert(val);
};
}
for (var i = 0; i < 2; i++) {
var myDiv = $('<div>');
myDiv.click(alertFn(i));
$('body').append(myDiv);
}
}
var myFunc = new MyFunc();
闭包在传递给函数时捕获“i”的值,允许alert()显示你期望的值。