在Javascript中声明var for循环声明

Ben*_*son 11 javascript variables scope for-loop

我确定我已经阅读过有关此问题的讨论,但找不到它.简单地说,是否有必要在循环声明中声明for循环的增量?这有什么区别:

function foo() {
    for (var i=0; i<7; i++) {
        // code
    }
}
Run Code Online (Sandbox Code Playgroud)

...还有这个:

function foo() {
    var i;
    for (i=0; i<7; i++) {
        // code
    }
}
Run Code Online (Sandbox Code Playgroud)

既然JS有功能范围,要么都应该没问题吧?是否存在前一种方法会导致问题的边缘情况?

如果它们完全相同,那么为什么Crockford/JSLint所有人,"没有办法",关于它?

Jar*_*Par 14

这些完全一样.javascript中的所有局部变量都具有函数作用域,这意味着它们对于声明它们的整个函数是活跃的.这通常是反直觉的,因为大多数大括号语言将变量的生命周期范围限定为声明它们的块.

一部分Javascript开发人员非常喜欢第二种形式.基本原理是,由于所有变量都具有函数范围,因此您应该在函数级别声明它们,以便即使对于那些不熟悉Javascript的人也可以显示生命周期.这只是一种风格,绝不是一个硬性规则

编辑

请注意,通过引入ES6 let,您现在可以在循环内部使用let来获取实际的块范围变量更多详细信息

for(let i = 1; i <= 5; i++) {
   setTimeout(function(){
       console.log('Value of i : ' + i);
   },100);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*eed 8

var在循环标题中声明的问题是它具有欺骗性.它看起来像你声明一个变量,其范围仅限于该for循环,当它实际上是在函数中存在的任何地方-包括之前的声明:

var i = 1;
function foo() {
   console.log(i);                     // 'undefined'
   for (var i=1; i<100; ++i) {
   }
}
Run Code Online (Sandbox Code Playgroud)

即使console.log调用发生在本地声明之前i,它仍然在它的范围内,因为它在同一个函数内.因此i,尚未赋予其任何价值的本地是传递给它的东西log.这可能是令人惊讶的; 对于那些不熟悉Javascript范围规则的人来说,这当然不是显而易见的.

ECMAScript 2015开始,有一种更好的方式来声明变量:let.声明的变量let是包含它们的块的本地变量,而不是整个函数.因此,上述代码的此版本1将按预期打印:

let i=1; // could use var here; no practical difference at outermost scope
function foo() {
  console.log(i);               // 1
  for (let i=1; i<100; ++i) {
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,现代Javascript中的最佳实践是使用let而不是声明变量var.但是,如果你坚持使用ECMAScript之前的2015实现,那么在函数顶部声明所有变量并不等到第一次使用时就不那么容易混淆了.