这是我第一次使用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>
当我点击“de”按钮然后点击“en”按钮时,日志会给我:
en
en
这似乎是在第二次调用中覆盖侦听器函数的效果,是吗?我该如何避免这种情况?
答案 0 :(得分:7)
更新后
在您更新的问题中$t
是一个全局变量。在JavaScript(通常)中,您在未事先放置var
的情况下声明的所有内容都是绑定到窗口的全局变量(在浏览器中)。
您可以修改代码,方法是将$t = ...
更改为var $t = ...
,这会在处理程序中声明$t
jQuery允许您将点击处理程序附加到多个按钮,而无需使用.each
来迭代它们。
您的代码应该可以工作,但是如果您以可能更改this
的方式调用处理程序可能会有问题(注意,您可以关闭this
(或使用bind)代码中的.each
以确保您获得相同的this
,您还可以尝试在每个代码中记录$(this).attr('id')
尝试:
$(function(){
$("button").click(function() {
console.log("Id: " + $(this).attr('id'));
});
});
(Your original code works too by the way (fiddle))
在处理程序中,jQuery返回您在$()
中包装的实际dom元素,以再次生成jQuery对象。您不需要构建jQuery对象只是为了获取ID,$(this).attr('id')
可以替换为this.id
。
答案 1 :(得分: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
,而{I}又不在处理程序之间共享。这解决了封闭问题。
请注意,我也可以命名最里面的函数参数$t
(在这种情况下,名称会隐藏迭代范围内的$t
);我选择不这样做只是为了清晰。