JavaScript变量不会在jQuery事件处理程序中持久存在

时间:2014-12-22 21:32:45

标签: javascript jquery event-handling scope

出于某种原因,我不了解与jQuery点击处理程序有关的局部变量和全局变量的范围。当我单击按钮时,我得到“未定义”,但我希望它显示单击按钮的类别。我该如何解决这个问题?

我已经设置了一个例子来表明我的困惑。在这里小提琴:http://jsfiddle.net/zvhsqeyn/

简单的html按钮:

<button class="hobbies">hobbies</button>
<button class="sledding">sledding</button>
<button class="personal">personal</button>
<button class="food">food</button>

一些javascript来处理单击按钮的事件。

var GLOBAL_CATEGORIES = ['hobbies', 'sledding'];

$(window).load(function() { 
    var categories = ['personal', 'food'];

    // local categories
    for (var i = 0; i < categories.length; i++) {
        $('.' + categories[i]).click(function() {
            alert(categories[i]);
            return false;
        });
    }

    // Global categories
    for (var i = 0; i < GLOBAL_CATEGORIES.length; i++) {
        $('.' + GLOBAL_CATEGORIES[i]).click(function() {
            alert(GLOBAL_CATEGORIES[i]);
            return false;
        });
    }
});

编辑: 在收到反馈后,这是正常工作的http://jsfiddle.net/zvhsqeyn/1/

2 个答案:

答案 0 :(得分:1)

这与闭包的性质有关。

// local categories
for (var i = 0; i < categories.length; i++) {
    $('.' + categories[i]).click(function() {
        alert(categories[i]);
        return false;
    });
}

您正在为每个按钮分配一个匿名函数作为单击处理程序。该函数可以访问变量i,因为它在父作用域中可见。 然而 - 当您单击其中一个按钮时,您的循环早已完成,i的值现在等于categories.length。那里没有任何元素,因此您的点击功能返回undefined

通常,在循环中分配事件处理程序时依赖索引变量的值是不安全的。作为解决方法,您可以使用jquery $ .each函数:

$.each(categories, function(index, value) {
    // local categories
    $('.' + value).click(function() {
        alert(value);
        return false;
    });
});

这是有效的,因为它为每个单击处理函数创建一个单独的闭包。

答案 1 :(得分:-2)

这是一个非常常见的问题,这里是解释

如果我们按照您正在执行的操作的过程,则向第i GLOBAL_CATEGORIES添加一个点击监听器,然后转到下一个。您执行此操作直到iGLOBAL_CATEGORIES数组太大。

您必须记住,i仅设置了一次,因此现在iGLOBAL_CATEGORIES的长度多1个。这意味着,由于GLOBAL_CATEGORIES[i]太大,警报触发i未定义。

更好的方法是使用jQuery each语法,如下所示

$.each(GLOBAL_CATEGORIES, function(i, category) {
    $('.' + category).click(function() {
        alert(category);
        return false;
    });
});