考虑以下代码:
for( var i = 1; i <= 2; ++i )
{
$( '#id' + i ).click(
function()
{
alert( 'ID = ' + i );
}
)
}
问题是,当点击id1或id2时,警报总是说ID = 3.现在我知道为什么会发生这种情况(在通话时评估),我只是好奇是否有办法防止这种情况发生? (1)
这里的许多问题和文章一般都很好地解释了闭包的概念,但是我无法找到任何避免它的技术。
在旁注中,我尝试使用(注意额外的关键字“new”):
new function() { alert( 'ID = ' + i ) }
然而,它在定义时直接调用警报,并且对点击事件不执行任何操作。有什么想法吗? (2)
答案 0 :(得分:2)
一种方式就是这样。
HTML
<div id="id1">ID1</div>
<div id="id2">ID2</div>
<div id="id3">ID3</div>
的Javascript
for (var i = 1; i <= 2; i += 1) {
(function (j) {
$('#id' + j).click(
function () {
alert('ID = ' + j);
});
}(i));
}
在 jsfiddle
上答案 1 :(得分:1)
基本上,您需要创建一个新的范围,i
的值不会改变。因此,为了说明,您可以在循环外创建函数,传递当前值:
function createClickAction(i){
return function(){
alert( 'ID = ' + i );
}
}
for(var i = 1;i <= 2; ++i){
$( '#id' + i ).click(
createClickAction(i)
);
}
但是,执行相同操作的更简单方法是将值传递给IIFE:
for(var i = 1;i <= 2; ++i){
(function(i){
$( '#id' + i ).click(
function(){
alert( 'ID = ' + i );
}
);
})(i);
}
以下是有关语法new function(){...}的一些讨论 它具有与IIFE相同的效果,因为您实例化一个自治函数,作为构造函数。所以就像说:
function Message(){
alert('hi');
}
new Message();
......但没有命名。
并传递参数:
new function(msg){
alert(msg)
}('hi');
所以你可能很接近找到这个解决方案:
for(var i = 1;i <= 2; ++i){
new function(i){
$( '#id' + i ).click(
function(){
alert( 'ID = ' + i );
}
);
}(i);
}
答案 2 :(得分:0)
怎么样 -
for( var i = 1; i <= 2; ++i )
{
$( '#id' + i ).click(
function()
{
alert( 'ID = ' + this.id.substring('#id'.length) );
}
)
}