Javascript 通过each()添加的jQuery事件处理程序似乎覆盖了以前的处理程序
这是我第一次使用jquery,我不理解以下“副作用”: script.js: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
$(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%确定您输入的代码正确