1

考虑这段代码:

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)

4

3 回答 3

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

于 2013-08-30T13:23:22.937 回答
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);
}
于 2013-08-30T13:36:23.640 回答
0

怎么样 -

for( var i = 1; i <= 2; ++i )
{
 $( '#id' + i ).click(
   function()
   {
     alert( 'ID = ' + this.id.substring('#id'.length) );
   }
  )
}
于 2013-08-30T13:13:17.057 回答