Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 通过each()添加的jQuery事件处理程序似乎覆盖了以前的处理程序_Javascript_Jquery_Closures - Fatal编程技术网

Javascript 通过each()添加的jQuery事件处理程序似乎覆盖了以前的处理程序

Javascript 通过each()添加的jQuery事件处理程序似乎覆盖了以前的处理程序,javascript,jquery,closures,Javascript,Jquery,Closures,这是我第一次使用jquery,我不理解以下“副作用”: script.js: $(function() { $("button").each(function() { $t=$(this); $t.on("click", function() { console.log("Id: " + $t.attr('id')); }); }); }); html: ... <body> <button

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

script.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>

这似乎是在第二次调用中覆盖侦听器函数的结果,对吗?如何避免这种情况?

更新后

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

您可以通过将
$t=…
更改为
var$t=…
来修复代码,这将在处理程序中声明
$t


jQuery允许您将单击处理程序附加到多个按钮,而无需使用
。每个按钮都可以通过
进行迭代

你的代码应该可以工作,但是如果你调用处理程序的方式可能会改变
这个
(注意,你可以在
中关闭
这个
(或者使用bind)。你的代码中的每个
都可以确保你得到相同的
这个
,你也可以尝试记录
$(这个)。attr('id'))
中的每个选项)

尝试:


在处理程序中,jQuery返回实际的dom元素,您将其包装在
$()
中以再次生成jQuery对象。您不需要构造jQuery对象来获取ID,
$(this).attr('ID')
可以在更新后替换为
this.ID

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

您可以通过将
$t=…
更改为
var$t=…
来修复代码,这将在处理程序中声明
$t


jQuery允许您将单击处理程序附加到多个按钮,而无需使用
。每个按钮都可以通过
进行迭代

你的代码应该可以工作,但是如果你调用处理程序的方式可能会改变
这个
(注意,你可以在
中关闭
这个
(或者使用bind)。你的代码中的每个
都可以确保你得到相同的
这个
,你也可以尝试记录
$(这个)。attr('id'))
中的每个选项)

尝试:

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

问题:闭包 由于存在
$t
,您的代码有一个与闭包相关的bug。发生的情况是,每个按钮上都安装了一个单击处理程序;所有这些单击处理程序都将该按钮称为
$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
隐藏在迭代范围之外);我选择不这样做只是为了清楚。

问题是:关闭 由于存在
$t
,您的代码有一个与闭包相关的bug。发生的情况是,每个按钮上都安装了一个单击处理程序;所有这些单击处理程序都将该按钮称为
$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
隐藏在迭代范围之外);我选择不这样做只是为了清楚。

当你做什么时,日志会告诉你这一点?你们已经附加了点击处理程序-你们点击了什么?我点击了每个按钮。首先是“de”,然后是“en”…这是一个与闭包相关的bug,但是显示的代码看起来没有。您是否100%确定您输入的代码正确