我知道这段代码不起作用,我也知道原因。 但是,我不知道如何解决它:
JavaScript的:
var $ = function(id) { return document.getElementById(id); };
document.addEventListener('DOMContentLoaded', function()
{
for(var i = 1; i <= 3; i++)
{
$('a' + i).addEventListener('click', function()
{
console.log(i);
});
}
});
HTML:
<a href="#" id="a1">1</a>
<a href="#" id="a2">2</a>
<a href="#" id="a3">3</a>
我希望它能够打印您点击的链接号,而不仅仅是“4”。 我宁愿避免使用节点的属性(id或content),而是修复循环。
答案 0 :(得分:5)
将循环块包装在自己的匿名函数中:
document.addEventListener('DOMContentLoaded', function()
{
for(var i = 1; i <= 3; i++)
{
(function(i) {
$('a' + i).addEventListener('click', function() {
console.log(i);
})
})(i);
}
}
这将创建一个i
的新实例,它在每次调用/迭代时都是内部函数的本地实例。如果没有这个本地副本,传递给addEventListener
的每个函数(在每次迭代中)都会关闭对相同变量的引用,其值等于4
时的任何一个那些回调执行。
答案 1 :(得分:3)
问题是内部函数正在i
创建一个闭包。从本质上讲,这意味着函数不仅仅是在设置处理程序时记住i
的值,而是变量i
本身;它保留了i
的实时参考。
您必须通过将i
传递给某个函数来打破关闭,因为这会导致i
的复制。
执行此操作的常用方法是使用立即执行的匿名函数。
for(var i = 1; i <= 3; i++)
{
$('a' + i).addEventListener('click', (function(localI)
{
return function() { console.log(localI); };
})(i);
}
由于你已经在使用jQuery,我会提到jQuery提供了一个data函数,可以用来简化这样的代码:
for(var i = 1; i <= 3; i++)
{
$('a' + i).data("i", i).click(function()
{
console.log($(this).data("i"));
});
}
这里,不是通过将i
传递给匿名函数来打破闭包,而是通过将i
传递给jQuery的data
函数来打破它。
答案 2 :(得分:0)
闭包捕获对变量的引用,而不是副本,这就是为什么它们都会导致'i'的最后一个值。
如果你想捕获一个副本,那么你需要将它包装在另一个函数中。