在Javascript中声明var for循环声明

时间:2012-04-18 00:13:12

标签: javascript variables for-loop scope

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

function foo() {
    for (var i=0; i<7; i++) {
        // code
    }
}

......而且这个:

function foo() {
    var i;
    for (i=0; i<7; i++) {
        // code
    }
}

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

如果它们完全相同,那么为什么Crockford / JSLint全都是“没办法”呢?

5 个答案:

答案 0 :(得分:12)

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

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

修改

请注意,通过引入ES6 let,您现在可以在循环中使用let来获取实际的块范围变量more details

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

答案 1 :(得分:7)

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

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

即使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) {
  }
}

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

答案 2 :(得分:1)

没有区别,但我更喜欢第二种方式(根据Crockford),因为它明确地显示了在for循环之外可用的变量:

function() {
    for(var i=0; i<7; i++) {
        // code
    }

    // i is still in scope here and has value 7
}

答案 3 :(得分:0)

这些都是完全相同的。

答案 4 :(得分:0)

两个代码块完全相同。 for循环的第一个语句在for循环开始之前执行,循环在第二个语句为true时运行,第三个语句在每次循环迭代一次时运行。

这意味着

for(var i = 0; i < 8; i++) {
    //some Code
}

相同
var i = 0;
for(;i < 8;) {
    //some Code
    i++;
}

(后面的分号是告诉计算机i < 8实际上是第二个语句,而不是第一个语句。