【问题标题】:What's the scope of a Javascript variable declared in a for() loop?在 for() 循环中声明的 Javascript 变量的范围是什么?
【发布时间】:2011-02-13 13:46:03
【问题描述】:

查看以下 HTML/Javascript 代码的 sn-p:

<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 的范围发生了什么,以及为什么匿名函数没有捕获它的值?

【问题讨论】:

    标签: javascript scope puzzle anonymous-function


    【解决方案1】:

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

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

    你需要一个真正的闭包。

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

    【讨论】:

    • 正确答案 - 谢谢! - 但我接受了 Pointy 的回答,因为“我自己的私人”+ idaho 让我大笑起来......
    【解决方案2】:

    在 Javasript 中,唯一“有趣”的词法范围边界是函数体。在函数的任何地方声明的任何东西(嗯,除了另一个嵌套函数之外的任何地方!)都在同一范围内。声明的解释方式也有一些奇怪的地方。

    您的匿名函数确实充当了一个闭包,但每个实例化的函数都将共享相同的“i”。我使用的一个技巧是添加另一层函数:

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

    希望在某个时候所有浏览器都支持新的“let”语句,这是一种更短、更不奇怪的方式来完成基本相同的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      • 2016-10-22
      • 2011-03-26
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多