-2

.append()我使用jQuery的方法遇到了一个奇怪的行为。

var container = $('#container');


var buttons = {
    'Okay': function() {
        return 'Yeah, I\'m okay with this.';
    },
    'Nope': function() {
        return 'No, no, definitively no.';
    },
    'Maybe': function() {
        return 'Hum, maybe.';
    }
};


for(var button_label in buttons) {
    var button_callback = buttons[button_label];

    var button_html = $('<button type="button">' + button_label + '</button>');

    button_html.on('click', function() {
        alert('button : ' + $(this).text() + ', callback : ' + button_callback());
    });

    container.append(button_html);
}

查看JS Bin上的代码

一切正常,除了,如您所见,单击所有按钮时:调用相同的回调(buttons对象中最后定义的回调)。我检查了 jQuery 的文档,也许这是相关的:

但是,如果有多个目标元素,则会为第一个目标之后的每个目标创建插入元素的克隆副本。

或者,我需要重构我的代码。我测试了不同的解决方案,但都没有奏效。任何人都可以帮助我吗?

4

1 回答 1

5

这是一个古老的“传递给回调的循环中的变量”问题,在 Stack Overflow 上存在十亿次。所以它根本与jQuery无关。

您需要做的是在每个循环期间创建一个新变量。最简单的方法是使用立即执行并接收值作为参数的匿名函数。

(function(button_callback) {
    button_html.on('click', function() {
        alert('button : ' + $(this).text() + ', callback : ' + button_callback());
    });
})(button_callback);

更新了 JSBin

为什么这是必要的?在 JavaScript 中没有块作用域。只有函数会创建新范围。所以在你的原始代码var button_callback中被提升到范围的顶部(包含你的循环或全局范围的函数,如果没有的话)。因此,在每次迭代中,您都有相同的变量。这个变量绑定到你的匿名函数的闭包。因此,在循环之后,变量具有最后一个值 - 在所有三个函数中。

于 2013-09-01T12:19:06.280 回答