![](/img/trans.png)
[英]Keep different variable's state in multiple anonymous asynchronous functions in a loop
[英]Defining anonymous functions in a loop including the looping variable?
我知道这段代码不起作用,我也知道原因。 但是,我不知道如何解决它:
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或内容),而是修复循环。
将循环块包装在自己的匿名函数中:
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
。
问题是内部函数正在创建一个关闭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提供了一个数据函数,可以用来简化这样的代码:
for(var i = 1; i <= 3; i++)
{
$('a' + i).data("i", i).click(function()
{
console.log($(this).data("i"));
});
}
在这里,而不是通过传递破封i
一个匿名函数时,你通过传递打破它i
到jQuery的data
功能。
闭包捕获对变量的引用,而不是副本,这就是为什么它们都会导致'i'的最后一个值。
如果要捕获副本,则需要将其包装在另一个函数中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.