【问题标题】:Variable definitions in nested for loops?嵌套for循环中的变量定义?
【发布时间】:2011-12-05 13:58:27
【问题描述】:

像 Java 这样的一些静态语言似乎对在 for 循环的第一个参数中定义的变量有非常特殊的规则。它们只能通过给定的循环访问,这使得它们的行为非常类似于 javascript 函数的局部变量和参数。我的意思是这样的:

class ForVariable {
  public static void main(String[] args) {
    for(int i = 0; i != 0; i++) {}
    System.out.println(i); // Throws an Exception
  }
}

Javascript 的行为并非如此,这使得嵌套循环变得非常混乱。我的问题是:在后续循环中通过 var 关键字声明变量是否有效?换句话说 - 以下哪个示例是有效的?

for(var i = 0, j; i < 5; i++) {
  for(j = 0; j < 10; j++) <do some stuff>;
}

for(var i = 0; i < 5; i++) {
  for(var j = 0; j < 10; j++) <do some stuff>;
}

显然,多次声明一个变量是错误的,这会使第二个示例无法进行,但鉴于第一个示例是我所知道的大多数语言中循环嵌套的方式,我宁愿犹豫着宣布获胜者。

【问题讨论】:

  • 仅在 javascript 函数作用域中没有块作用域的概念,在循环声明中(或在 ifs 中)使用 var 关键字与使用 var 声明的效果相同函数开头的关键字。 (不像 Java、C 和其他)
  • 对。但这意味着嵌套循环中的那些vars 将被执行多次,这似乎不是一个有效的解决方案,或者?
  • 多次使用var没有实际问题(但有时可能是逻辑错误)。在这种情况下(循环块),变量也只能在循环块之外访问,如果您期望块范围以防您为变量使用相同的名称,您可能会遇到奇怪的问题。

标签: javascript loops for-loop nested-loops


【解决方案1】:

这些都是有效的。 Function scoped 与块范围。基本上 JavaScript 中的两个循环都变成:

function a () {
    var i, j;
    for(i = 0, j; i < 5; i++) {
      for(j = 0; j < 10; j++) <do some stuff>;
    }
}

因为var 声明在顶部是hoisted

【讨论】:

  • 嗯,a = 1; 在全局范围内执行将与var a = 1; var a = 1; var a = 1; 具有相同的效果。但是,这并不能使它们中的任何一个成为有效的变量定义,这就是我的问题所在。
  • 我告诉过你它们都是有效的朋友,但我试图解释为什么它们都是有效的,因为 JavaScript 中的提升和作用域
  • 好的,感谢您提供的详细信息,我明白您的意思。 :-)
【解决方案2】:

多次声明一个变量并没有错误。例如确实没有问题:

var i = 0;
var i = 1;

这是有效的 JavaScript。但是像 Closure Compiler 这样的好工具会生成警告,因为您通常不打算这样做。

话虽如此,即使闭包编译器也不会为您的示例 #2 生成警告。即使您在技术上重新声明,这只是 JS 中的常见约定。

您的两个示例中的任何一个都很好,但第二个示例更易于解析。无论哪种方式,我都不会担心。

【讨论】:

  • 感谢您的回答。然而,在同一个范围内多次声明同一个变量不是不好的做法吗? vars 和 functions 是 javascript 中的一等公民,这可能会使范围的准备工作稍微慢一些,不是吗?
  • 好吧,编译器实际上只会在函数开始时声明一次,因此在运行时不会变慢。查找“JavaScript 提升”以了解原因。
【解决方案3】:

您不想使用 var 关键字,而是使用函数参数,因为 javascript 不是块范围的。例如:

[100,200,300].forEach(function (x,i) {
    [10,20,30].forEach(function (y,j) {
        console.log('loop variables, indices '+[i,j]+' have values: '+[x,y]);
    });
})

[100,200,300].map(function (x,i) {
    return [10,20,30].map(function (y,j) {
        return x+y;
    });
})

// result: [[110,120,130],[210,220,230],[310,320,330]]

【讨论】:

  • 是的,正如我所说,这是一项混乱的业务,这使得 ECMA5 方法成为一种幸福。但是,这并不能真正回答我的问题。 :-)
  • @Witiko:啊,哎呀,一个真正了解事情的开发人员。 =) 抱歉,我以为您只是在问“如何使嵌套的 for 循环工作?”不是一个深入的句法问题。希望其他人可以阐明,或者您可以查看ecma-international.org/publications/standards/Ecma-262.htm 祝您好运。 (不妨在这里留下答案以供其他人参考。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多