JavaScript“for-in”循环中的“var”或没有“var”?

时间:2011-04-19 13:28:54

标签: javascript syntax for-in-loop

在JavaScript中编写for-in循环的正确方法是什么?浏览器不会对我在此处显示的两种方法中的任何一种发出投诉。首先,有一种方法,其中显式声明了迭代变量x

for (var x in set) {
    ...
}

另外,这种方法更自然,但对我来说似乎不正确:

for (x in set) {
    ...
}

10 个答案:

答案 0 :(得分:98)

使用var,它减少了变量的范围,否则变量会查找最近的闭包,搜索var语句。如果它找不到var那么它是全局的(如果你处于严格模式using strict,则全局变量会抛出错误)。这可能会导致以下问题。

function f (){
    for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

如果您在for循环中写var i,则警告会显示2

JavaScript Scoping and Hoisting

答案 1 :(得分:34)

第一个版本:

for (var x in set) {
    ...
}

声明一个名为x的局部变量。第二个版本:

for (x in set) {
    ...
}

没有。

如果x已经是一个局部变量(即你当前范围中的某个地方(即当前函数)有某个var x;var x = ...;),那么它们将是等价的。如果x不是本地变量,那么使用第二个将隐式声明全局变量x。请考虑以下代码:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

您可能希望此提醒heythereheliheytherecopter,但自{{ 1}}是同一个警告xheytherethereheythere。你不希望这样!在there循环中使用var x

最重要的是:如果for循环在全局范围内(即不在函数中),那么如果使用{{},则声明范围for。 1}})与全局范围相同(如果使用x而没有var,则隐式声明范围var x,因此两个版本将完全相同。

答案 2 :(得分:20)

你真的应该用var声明局部变量,总是

你也不应该使用“for ... in”循环,除非你完全确定那是你想要做的。对于迭代真实数组(这是很常见的),你应该总是使用带有数字索引的循环:

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

使用“for ... in”迭代一个普通数组可能会产生意想不到的后果,因为除了数字索引的数组之外,你的循环可能会获取数组的属性。

编辑 - 在2015年,使用.forEach()迭代数组也很好:

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

来自IE9的Array原型上存在.forEach()方法。

答案 3 :(得分:11)

实际上,如果你不喜欢for标题内的声明,你可以这样做:

var x;
for (x in set) {
    ...
}

正如在这个问题的其他答案中所提到的,完全不使用var会产生不必要的副作用,例如分配全局属性。

答案 4 :(得分:9)

使用var声明循环变量的那个。隐式声明的变量具有不同的范围,可能与您的意图不同。

答案 5 :(得分:6)

for(var i = 0; ...)

是一种常见的模式,但它与

不同
for(int i; ...)

在C ++中,变量没有作用于for块。事实上,var被提升到封闭范围(函数)的顶部,因此本地i将在for循环之前(在当前范围开始之后)有效可用/功能)之后。

换句话说,做:

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

与:

相同
(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6使用let关键字(而不是var)将范围限制为for块。

当然,您应该使用局部变量(使用varletconst(在ES6中)声明的变量)而不是隐式全局变量。

如果您使用for(i=0; ...)(如您所愿)并且未声明for(i in ...),则

"use strict";i将失败。

答案 6 :(得分:5)

使用var是最干净的方式,但两者都按照此处所述工作:https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in

基本上,通过使用var,您可以确保创建新变量。否则,您可能会意外地使用先前定义的变量。

答案 7 :(得分:4)

我认为var对性能有好处。

Javascript不会查看整个全局范围,以查看x是否已经存在于其他地方。

答案 8 :(得分:3)

从一般的角度来看,第一个版本将用于必须存在于循环范围内的索引,而另一个版本将是调用循环构造函数的范围内的任何变量。

如果要在for循环中使用循环索引,并且下一行中的其他人不需要这样,那么最好用“var”声明变量,这样你就可以确定“x”是循环索引初始化的0,而另一个,如果在这个上下文中有其他“x”变量可用,这将被循环索引覆盖 - 这就是你会有一些逻辑错误 - 。

答案 9 :(得分:0)

我总是使用ES2015中引入的块范围let

for (let x in set) {
    ...
}

Additional reading and examples