【问题标题】:Javascript loop with binded click event always returning last result带有绑定点击事件的Javascript循环总是返回最后一个结果
【发布时间】:2011-12-26 19:30:24
【问题描述】:

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

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

for(e in data) {

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

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

    suggestList.append(suggestItem);

}

我想我明白为什么会发生这种情况,但不知道应该如何处理。

【问题讨论】:

标签: javascript jquery loops


【解决方案1】:

这是一个经典的 Javascript 闭包问题。当点击事件被触发时(当你点击某物时),循环已经完成执行。 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]);
}

Javascript 是函数作用域,因此每当遇到新函数时,都会创建一个新作用域。上面的代码将data[e] 的值“捕获”到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);      
            });
        );
    })();
}

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

另外请注意for(VAR e in data) 将阻止e 成为全局变量。

【讨论】:

    【解决方案2】:

    你需要打破e 的闭包。

    由于您使用的是 jQuery,最简单的方法是使用 jQuery 的 data 函数保存 e 的当前值。由于 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);
    
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-05
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-22
      相关资源
      最近更新 更多