【问题标题】:JavaScript variables do not persist in jQuery event handler [duplicate]JavaScript变量不会保留在jQuery事件处理程序中[重复]
【发布时间】:2014-12-22 21:32:45
【问题描述】:

出于某种原因,我不了解与 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/

【问题讨论】:

  • 尝试在你的循环中提醒i,看看会发生什么。这可能会让您了解实际发生的情况。
  • 你为什么使用$(window).load(function(){...})而不是jQuery ready()或者干脆$(function({...}))
  • @GriffeyDog 也许他也想等待图像完成加载。

标签: javascript jquery event-handling scope


【解决方案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;
    });
});

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

【讨论】:

    【解决方案2】:

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

    如果我们按照您正在执行的流程进行操作,则将点击侦听器添加到第 i 个 GLOBAL_CATEGORIES,然后继续进行下一个。你这样做直到i 对于GLOBAL_CATEGORIES 数组来说太大了。

    你必须记住i 只设置了一次,所以现在iGLOBAL_CATEGORIES 的长度多1。这意味着当警报触发时GLOBAL_CATEGORIES[i] 是未定义的,因为i 太大了。

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

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

    【讨论】:

      猜你喜欢
      • 2016-04-17
      • 2013-04-28
      • 1970-01-01
      • 2013-07-04
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多