在创建时使用范围内的变量绑定单击处理程序? [英] Bind click handler with variables in scope when created?
问题描述
我想在jQuery中动态创建项目列表,并动态地将单击处理程序绑定到每个项目,并在创建单击处理程序时将变量放在范围内。
I'd like to create a list of items dynamically in jQuery, and dynamically bind a click handler to each one, with the variables in scope at the moment the click handler is created.
下面的代码创建1-6的项目列表,但点击处理程序似乎只与最终项目的值绑定 - 警报始终显示6。
The code below creates a list of items from 1-6, but the click handler only seems to bind with the value of the final item - the alert always shows 6.
这是一个JavaScript范围问题吗?如何使用1-6中的变量绑定警报?
Is this a JavaScript scope problem? How can I bind the alerts with variables from 1-6?
HTML:
<ul id="saved-list">
</ul>
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);
}
请参阅jsFiddle: http://jsfiddle.net/n6FU5/
See jsFiddle here: http://jsfiddle.net/n6FU5/
推荐答案
这是范围和花括号之间经典的JavaScript混淆。事实证明,花括号与JavaScript中的范围几乎没有关系。范围仅来自函数。
This is a classic JavaScript confusion between "scope" and "curly braces". It turns out that curly braces have little to do with scope in JavaScript. Scope only arises from functions.
这样做的一个结果是变量总是被提升到范围的顶部,即最近的函数。所以你的代码完全等同于:
One consequence of this is that variables are always hoisted to the top of the scope, i.e. the nearest function. So your code is exactly equivalent to:
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);
}
考虑到这一点,你可以看到,因为 route_num
每次循环都是相同的变量,循环结束后它的值被设置为 6
,并且将来每当调用click处理程序,你看到 6
。
With this in mind, you can see how, since route_num
is the same variable every time through the loop, after the loop is over its value is set to 6
, and in the future whenever the click handler is called, the 6
is what you see.
解决这个问题的一种方法是包装内容循环在自执行匿名函数中:
One way to fix this is to wrap the contents of your loop in a self-executing anonymous function:
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);
}());
}
这样,当变量被提升时,它们将被提升到该内部自执行函数的顶部,因此每次循环运行时都会有不同的实例。
That way, when the variables get hoisted, they will just get hoisted to the top of that inner self-executing function, and so there will be different instances of them for each run through the loop.
这篇关于在创建时使用范围内的变量绑定单击处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!