2010-04-28 59 views
10

退房的HTML/Javascript代码下面的代码片段:for()循环中声明的Javascript变量的作用域是什么?

<html> 
<head> 
<script type="text/javascript"> 
var alerts = []; 
for(var i = 0; i < 3; i++) { 
    alerts.push(function() { document.write(i + ', '); }); 
} 

for (var j = 0; j < 3; j++) { 
    (alerts[j])(); 
} 

for (var i = 0; i < 3; i++) { 
    (alerts[i])(); 
} 
</script> 
</head><body></body></html> 

此输出:

3, 3, 3, 0, 1, 2 

这不是我所期待的 - 我期待输出0, 1, 2, 0, 1, 2,

我(错误地)认为被推入到数组中的匿名函数会表现为闭包,捕获创建函数时分配的值i - 但它实际上似乎是i表现为全局变量。

任何人都可以解释这个代码示例中i的范围发生了什么,以及为什么匿名函数没有捕获它的值?

回答

6

在Javasript中,唯一“有趣”的词汇范围边界是函数体。在函数中任何地方声明的任何东西(以及除另一个嵌套函数以外的任何地方)都处于相同的范围。关于解释声明的方式也有一些奇怪的事情。

您的匿名函数确实充当闭包,但实例化的每个函数将共享相同的“我”。我用一个小窍门是添加的功能另一层:

for (var i = 0; i < whatever; i++) { 
    (function(idaho) { 
    whatever(function() { alert("my own private " + idaho); }); 
    })(i); 
} 

在somepoint希望所有的浏览器将支持新的“让”的声明,这是一个短,少看起来怪怪的方式基本上做同样的事情。

8

范围是变量定义的函数(除了没有一个,所以它是全局的)。

您传递的匿名函数正在访问在父函数(又是全局)范围中定义的变量。

您需要实际关闭。

alerts.push(
    function (foo) { 
     return function() { 
      document.write(foo + ', '); 

     } 
    }(i) 
); 
+0

正确答案 - 谢谢! - 但我接受了Pointy的回答,因为“我自己的私人”+爱达荷让我大声笑出声来...... – 2010-04-28 22:14:07