带有绑定点击事件的Javascript循环始终返回最后结果

Jus*_*son 5 javascript jquery loops

我有一个在javascript中运行的for循环.在这个循环中,我创建了一个列表项并将click事件绑定到它.当我单击此列表项时,我希望它使用当前循环对象中的数据作为参数调用函数.

问题是,无论我点击什么列表项.作为参数传递的数据是我循环的对象的最后一个元素,而不是当前被单击的对象.

for(e in data) {

    var suggestItem = $('<li>'+ data[e]['name'] +'</li>');

    suggestItem.click(function() {
        $(this).addClass('activeSuggestion');
        suggestSelect(suggestField, data[e]);      
    });

    suggestList.append(suggestItem);

}
Run Code Online (Sandbox Code Playgroud)

我想我明白为什么会这样,但不知道我应该如何处理它.

And*_*Ray 5

这是一个经典的Javascript闭包问题.当触发click事件时(当你点击某些东西时),循环已经完成执行.值e是无论最后一个键是什么data.该问题的解决方案是在循环内创建一个新范围.

for(var e in data) {
    (function(datum) {
        suggestList.append(
            $('<li>' + datum.name + '</li>')
            .click(function() {
                $(this).addClass('activeSuggestion');
                suggestSelect(suggestField, datum);      
            });
        );
    })(data[e]);
}
Run Code Online (Sandbox Code Playgroud)

Javascript是函数作用域,因此每当遇到新函数时,都会创建一个新的作用域.上面的代码"捕获"了data[e]into 的值,datum因为它将它作为参数传递给函数.另一种编码方式可能不那么令人困惑:

for(var e in data) {
    (function() {
        var datum = data[e];
        suggestList.append(
            $('<li>' + datum.name + '</li>')
            .click(function() {
                $(this).addClass('activeSuggestion');
                suggestSelect(suggestField, datum);      
            });
        );
    })();
}
Run Code Online (Sandbox Code Playgroud)

它不会将参数传递给函数,但由于Javascript是函数作用域,因此每次触发click事件时,它都会查找datum已分配的位置.

另请注意,for(VAR e in data)哪个将不再e成为全局变量.


Ada*_*kis 3

你需要打破封闭e

由于您使用的是 jQuery,最简单的方法是e使用 jQuerydata函数保存当前值。由于 JavaScript 中的所有函数参数都是按值传递的,因此这有效地破坏了闭包;e现在,您的点击处理程序将使用创建处理程序时的值,而不是e循环结束时的值。

for(e in data) {

    var suggestItem = $('<li>'+ data[e]['name'] +'</li>');

    suggestItem.data('savedE', e).click(function() {
        $(this).addClass('activeSuggestion');
        suggestSelect(suggestField, data[$(this).data('savedE')]);
    });

    suggestList.append(suggestItem);

}
Run Code Online (Sandbox Code Playgroud)