1

这是我第一次使用 jquery,我不明白以下“副作用”:

脚本.js:

$(function() {
  $("button").each(function() { 
    $t=$(this);                 
    $t.on("click", function() {
      console.log("Id: " + $t.attr('id'));
    });
  });
});

html:

...
<body>
  <button id="de">de</button>
  <button id="en">en</button>
</body>

当我单击“de”按钮然后单击“en”按钮时,日志给了我:

en
en

好像是在第二次调用中覆盖了监听函数的效果吧?我该如何避免这种情况?

4

2 回答 2

7

更新后

在您更新的问题$t中是一个全局变量。在 JavaScript 中(通常),您没有var提前声明的所有内容都是绑定到窗口(在浏览器中)的全局变量。

$t = ...您可以通过更改在处理程序中var $t = ...声明的来修复您的代码$t


jQuery 允许您将单击处理程序附加到多个按钮,而无需.each遍历它们。

您的代码应该可以工作,但如果您以可能会更改的方式调用处理程序,则可能会出现问题this(注意,您可以在代码中关闭this(或使用绑定).each以确保您得到相同的结果this,您也可以尝试登录$(this).attr('id')每个)

尝试:

$(function(){
  $("button").click(function() {                     
      console.log("Id: " + $(this).attr('id'));
  });
});

这是一个工作小提琴

(顺便说一句,您的原始代码也可以使用(小提琴))

在处理程序中,jQuery 返回您包装的实际 dom 元素$()以再次创建 jQuery 对象。你不需要构造一个 jQuery 对象来获取 ID,$(this).attr('id')可以替换为this.id.

于 2013-05-08T08:03:49.793 回答
2

问题:关闭

您的代码有一个由$t. 发生的情况是每个按钮上都安装了一个点击处理程序;所有这些点击处理程序都将按钮称为$t. 这意味着在安装处理程序时获取对的引用,并在调用处理程序时$t对其进行评估。

应该很容易看出这是怎么回事:当调用任何处理程序时,循环已经完成,$t最后一个按钮的值也已迭代。实际上,每个按钮都有一个处理程序,其操作就像最后一个按钮被单击一样。

如何解决

一种方法是首先避免创建闭包:

$(function() {
  $("button").each(function() { 
    $(this).on("click", function() {
      console.log("Id: " + $(this).attr('id'));
    });
  });
});

$t,没问题。你实际上可以把它写成

$(function() {
  $("button").on("click", function() {
    console.log("Id: " + $(this).attr('id'));
  });
});

否则,您需要确保每次循环迭代$t不同$t。做到这一点的方法是将范围限制$t在循环体中。由于 JavaScript 具有函数作用域,因此唯一的方法是在现场引入和调用函数:

$(function() {
  $("button").each(function() { 
    var $t=$(this);
    (function($u) {
      $u.on("click", function() {
        console.log("Id: " + $u.attr('id'));
      });
    })($t);
  });
});

在这个版本中,每个处理程序实际上都依赖于$u,而处理程序之间又不共享它。这解决了闭包问题。

请注意,我也可以命名最内层的函数参数$t(在这种情况下,该名称将隐藏$t在迭代范围内);我选择不这样做只是为了清楚。

于 2013-05-08T08:15:03.580 回答