2013-04-03 39 views
0
for (var i=0, link; i<5; i++) { 
    link = document.createElement("a"); 
    link.innerHTML = "Link " + i; 
    link.onclick = function (num) { 
     return function() { 
      alert(num); 
     }; 
    }(i); 
    document.body.appendChild(link); 
} 

由于嵌套函数是它具有与num参数的引用的封闭件,在循环结束时的num参数是4。现在时被点击的第一个元素为什么它提醒1?它应该提醒4。提醒1的原因是什么?不要参考num的论点?或者是什么原因?的Javascript闭合和其范围

但这里的情况是不同的:

function foo(x) { 
    var tmp = 3; 
    return function (y) { 
     alert(x + y + (++tmp)); 
    } 
} 
var bar = foo(2); // bar is now a closure. 
bar(10); 

上述功能将提醒16,因为酒吧仍然可以参考精氨酸xtmp,即使它不再直接范围内。

这证明,所述封闭也有参考参数值比为什么上面的代码不告警4每次?

+3

的第一个元素上点击,因为你正在传递参数'i'在当前迭代到具有参数内'onclick'功能时,它提醒''1' num' 。 –

+1

[这个问题在SO](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work)有一些很好的答案,可以帮助你理解闭包 – excentris

+1

它实际上应该是提醒0,因为那是您通过的第一个# –

回答

3
for (var i=0, link; i<5; i++) { //i starts at 0 and iterates up to 4 
     link = document.createElement("a"); 
     link.innerHTML = "Link " + i; 


     link.onclick = function (num) { 
      //num is never changed within this function, and is equal 
      //to the value of i when it was passed in 

      return function() { alert(num);}; 

     }(i); //i is passed here 
     //that sets num to the current value of i for each link 

     document.body.appendChild(link); 
    } 

对于第一个链接num将是0,因为i是它传递给外部函数时的一个。然后,我为循环的每一次迭代进行迭代,并且对于每个链接将是不同的值。

这里的模式是保留在回调/事件绑定一个循环迭代的当前值一个很常见的模式。

+0

因此不会在第一次点击时引用参数num的事件处理程序? –

+2

是的。当onclick属性第一次被设置时,'num'被闭包保存为'i'的值。 –

0

你在做什么是的典型例子,避免点击第一个元素会给你4而不是1,这应该是最期望的值。

如果你想让它提醒1,那么就这样做:

link.onclick = function() {alert(i);}; 

但说实话,这将是这点?所有4个链接将提醒4 ...