我使用jQuery的.append()
方法面临一种奇怪的行为。
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);
}
一切正常,但是,正如您所看到的,当点击所有按钮时:调用相同的回调(最后在buttons
对象中定义)。我检查了jQuery的doc,也许这是相关的:
但是,如果有多个目标元素,则会在第一个目标元素之后为每个目标创建插入元素的克隆副本。
或者,我需要重构我的代码。我测试了不同的解决方案,但都没有。有人可以帮帮我吗?
答案 0 :(得分:5)
这是传递给回调的循环中的一个好的“变量”问题,它存在于Stack Overflow上十亿次。所以它根本与jQuery无关。
您需要做的是在每个循环期间创建一个新变量。最简单的方法是使用一个立即执行的匿名函数,并将该值作为参数接收。
(function(button_callback) {
button_html.on('click', function() {
alert('button : ' + $(this).text() + ', callback : ' + button_callback());
});
})(button_callback);
为什么这有必要?在JavaScript中没有块范围。只有函数才能创建新范围。因此,在原始代码中var button_callback
被提升到范围的顶部(包含循环的函数或全局范围,如果没有)。因此,在每次迭代中,您都有相同的变量。并且此变量绑定到匿名函数的闭包。因此,在循环之后,变量具有最后一个值 - 在所有三个函数中。