创建时将单击处理程序与作用域中的变量绑定

Bind click handler with variables in scope when created?

本文关键字:作用域 变量 绑定 程序 单击 处理 创建      更新时间:2023-09-26

我想在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/

这是JavaScript中"scope"answers"大括号"之间的典型混淆。事实证明,大括号与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);      
    }());
} 

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

您遇到的问题是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);       
}

这是因为javascript的工作方式。正如您所发现的,作用域中的变量是可访问的,但它们不是每个子作用域的单独实例。因此,在调用处理程序函数时,变量的值为IS6。

解决方案是将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/