在JavaScript中编写for-in
循环的正确方法是什么?浏览器不会对我在此处显示的两种方法中的任何一种发出投诉。首先,有一种方法,其中显式声明了迭代变量x
:
for (var x in set) {
...
}
另外,这种方法更自然,但对我来说似乎不正确:
for (x in set) {
...
}
答案 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
。
答案 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();
您可能希望此提醒hey
,there
,heli
,hey
,there
,copter
,但自{{ 1}}是同一个警告x
,hey
,there
,there
,hey
,there
。你不希望这样!在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块。
当然,您应该使用局部变量(使用var
或let
或const
(在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)