我想在jQuery中动态创建项目列表,并动态地将单击处理程序绑定到每个项目,并在创建单击处理程序时将变量放在范围内.
下面的代码创建了1-6的项目列表,但是单击处理程序似乎只与最终项目的值绑定 - 警报始终显示6.
这是JavaScript范围问题吗?如何使用1-6中的变量绑定警报?
HTML:
<ul id="saved-list">
</ul>
Run Code Online (Sandbox Code Playgroud)
JS:
var all_cookies = [1,2,3,4,5,6];
for (var i = 0; i < all_cookies.length; i++) {
var route_num = all_cookies[i];
var list_item = "<li><a href='#saved-route'>";
list_item += "<p>" + route_num + "</p></a></li>";
var newLi = $(list_item);
newLi.bind('click', function(){
alert(route_num);
});
$('#saved-list').append(newLi);
}
Run Code Online (Sandbox Code Playgroud)
请参见jsFiddle:http://jsfiddle.net/n6FU5/
这是"范围"和"花括号"之间经典的JavaScript混淆.事实证明,花括号与JavaScript中的范围几乎没有关系.范围仅来自功能.
这样做的一个结果是变量总是被提升到范围的顶部,即最近的函数.所以你的代码完全等同于:
var all_cookies = [1,2,3,4,5,6];
var i;
var route_num;
var list_item;
var newLi;
for (i = 0; i < all_cookies.length; i++) {
route_num = all_cookies[i];
list_item = "<li><a href='#saved-route'>";
list_item += "<p>" + route_num + "</p></a></li>";
newLi = $(list_item);
newLi.bind('click', function(){
alert(route_num);
});
$('#saved-list').append(newLi);
}
Run Code Online (Sandbox Code Playgroud)
考虑到这一点,您可以看到,因为route_num每次循环时都是相同的变量,循环结束后它的值被设置为6,并且将来每当调用单击处理程序时,6就是您所看到的.
解决此问题的一种方法是将循环内容包装在一个自执行的匿名函数中:
var all_cookies = [1,2,3,4,5,6];
for (var i = 0; i < all_cookies.length; i++) {
(function () {
var route_num = all_cookies[i];
var list_item = "<li><a href='#saved-route'>";
list_item += "<p>" + route_num + "</p></a></li>";
var newLi = $(list_item);
newLi.bind('click', function(){
alert(route_num);
});
$('#saved-list').append(newLi);
}());
}
Run Code Online (Sandbox Code Playgroud)
这样,当变量被提升时,它们将被提升到内部自执行函数的顶部,因此每次运行循环时都会有不同的实例.