107

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

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

或者,这种读起来更自然但对我来说似乎不正确的方法:

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

10 回答 10

111

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

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

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

JavaScript 作用域和提升

于 2011-04-19T13:36:48.843 回答
41

第一个版本:

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,但由于x是一个且相同的,它会提醒hey, there, there, hey, there, there. 你不想要那个!var x在你的for循环中使用。

最重要的是:如果for循环在全局范围内(即不在函数中),则本地范围(x如果使用 ,则声明范围var x)与全局范围相同(范围x隐式声明在如果你x不使用 var),那么这两个版本将是相同的。

于 2011-04-19T13:39:44.100 回答
25

var你真的应该用, always声明局部变量。

你也不应该使用“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 开始,该.forEach()方法出现在 Array 原型上。

于 2011-04-19T13:32:13.070 回答
12

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

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

正如该问题的其他答案所述,根本不使用var会产生不必要的副作用,例如分配全局属性。

于 2011-04-19T14:01:44.303 回答
9

使用用 . 声明循环变量的那个var。隐式声明的变量具有不同的范围,这可能不是您想要的。

于 2011-04-19T13:30:43.447 回答
9
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 块的范围。

当然,你应该使用局部变量(在 ES6 中使用varorlet或 or声明的变量const)而不是隐式全局变量。

for(i=0; ...)或者for(i in ...)如果你使用"use strict";(你应该)并且i没有被声明,将会失败。

于 2015-05-22T15:23:18.257 回答
6

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

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

于 2011-04-19T13:30:26.957 回答
4

我认为 var 出于性能原因是好的。

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

于 2011-04-19T13:31:36.940 回答
3

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

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

于 2011-04-19T13:33:08.670 回答
0

我总是使用letES2015 中引入的块作用域。

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

附加阅读和示例

于 2020-11-06T17:53:05.410 回答