代码之家  ›  专栏  ›  技术社区  ›  Dylan Beattie

在for()循环中声明的javascript变量的作用域是什么?

  •  10
  • Dylan Beattie  · 技术社区  · 15 年前

    查看以下HTML/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 这是在创建函数时分配的-但实际上 作为全局变量运行。

    有人能解释一下 在这个代码示例中,为什么匿名函数没有捕获其值?

    2 回复  |  直到 15 年前
        1
  •  6
  •   Pointy    15 年前

    在javascript中,唯一“有趣”的词汇范围边界是函数体。函数中任何地方声明的任何内容(好吧,除了另一个嵌套函数!)在同一范围内。声明的解释方式也有些奇怪。

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

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

    在某种程度上,希望所有的浏览器都能支持新的“let”语句,这是一种更短、看起来不那么奇怪的方法,基本上可以做相同的事情。

        2
  •  8
  •   Quentin    15 年前

    作用域是在其中定义变量的函数(除了没有,所以它是全局的)。

    正在传递的匿名函数正在访问父函数(也是全局函数)作用域中定义的变量。

    你需要一个真正的结束。

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