我确信我已经阅读过有关此问题的讨论,但却无法找到。简单地说,是否有必要在循环声明中声明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全都是“没办法”呢?
答案 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
实际上是第二个语句,而不是第一个语句。