在创建时使用范围内的变量绑定单击处理程序?

时间:2011-05-29 17:41:31

标签: javascript jquery

我想在jQuery中动态创建项目列表,并动态地将单击处理程序绑定到每个项目,并在创建单击处理程序时将变量放在范围内。

下面的代码创建1-6的项目列表,但点击处理程序似乎只与最终项目的值绑定 - 警报始终显示为6.

这是JavaScript范围问题吗?如何使用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/

3 个答案:

答案 0 :(得分:5)

这是“范围”和“花括号”之间的经典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);      
}   

考虑到这一点,你可以看到,因为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);      
    }());
} 

这样,当变量被提升时,它们将被提升到该内部自执行函数的顶部,因此每次运行循环时都会有不同的实例。

答案 1 :(得分:2)

您遇到的问题是您的onclick函数在单击链接时返回变量route_num的值。 route_num是一个全局变量,当循环结束运行时,该值设置为6。所以你需要做的是设置函数以在for循环运行时警告route_num的值。

执行此操作的方法是将函数构造为字符串,以便可以将字符串的值附加到函数定义。这是我想要完成的想法的一个例子。

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);

    var fn = new Function("alert('" + route_num + "');");
    newLi.bind('click', fn); 

    $('#saved-list').append(newLi);       
}

答案 2 :(得分:1)

这是因为javascript的工作方式。范围内的变量可以在您发现时访问,但它们不是每个子范围的单独实例。因此,在调用处理函数时,变量的值为IS 6。

解决方案是将route_num保存在数据属性中,并在点击处理程序中检索它。

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.data('routenum', route_num);
    newLi.bind('click', function() {
        alert($(this).data('routenum'));
    });

    $('#saved-list').append(newLi);
}

这是你固定的小提琴:http://jsfiddle.net/n6FU5/1/