变量作用域和事件处理程序



请参阅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();

我想让潜水艇发出警报";0";以及";1〃;当我点击它们时,它们都会发出警报";2〃;。

当我单击div并触发事件时,处理程序如何以及在哪里找到变量i的值?

我知道添加闭包可以实现我的目标。但为什么呢?

    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发布到闭包中,让运行时"记住"那一刻的值。

您需要一个闭包,因为所有事件处理程序函数都引用了相同的变量ifor循环对此进行更新,当循环完成时,变量包含2。然后,当有人点击其中一个DIV时,它就会访问该变量。

为了解决这个问题,每个事件处理程序都需要是一个具有自己的变量i的闭包,该变量包含创建闭包时值的快照。

我建议您阅读这篇文章

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();
"alert()"调用发生在for循环完成之后,这意味着"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()显示您期望的值。

相关内容

  • 没有找到相关文章

最新更新