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


99

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

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

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

for (x in set) {
    ...
}

故障排除为什么产生捆绑文件的WebPack在一个导致错误的循环在当对面此帖一var不习惯声明迭代器iUncaught ReferenceError: i is not defined。因此,我将从现在开始使用它:/ webpack奇怪地对待“全局”变量,有关更多信息,请参见: stackoverflow.com/a/40416826
user1063287

Answers:


103

使用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

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

JavaScript范围界定和提升


4
不回答这个问题,这是正常的循环,而不是在。
IllidanS4希望莫妮卡回到

是i == 5的原因,不是因为for循环中缺少var而导致的?
Snekse 2013年

1
另一个重要方面是,严格模式禁止隐式创建gobal属性,因此使用不带var的标准“ for in”循环,var语句实际上将失败并返回ReferenceError。
dkugappi 2013年

2
但是,来自Java,将var内部置于for头部似乎是在for循环中是局部的,实际上不是。因此,我更喜欢下面的user422039样式。
njlarsson 2014年

2
如果您碰巧在一个示波器中有多个for循环该怎么办?您将不得不重用索引(无变量),或者必须声明很多新变量(j,k,l,m,…),而这些新变量将不再使用。
阿明2015年

40

第一个版本:

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,但因为x是一个,它会提醒一样heytherethereheytherethere。你不要那个!var xfor循环中使用。

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


3
最后是一个完整的答案,上面有解释和漂亮的例子。它确实回答了这个问题。
IllidanS4希望莫妮卡回到2012年

22

你真的应该声明局部变量用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
  ...
});

.forEach()从IE9开始,该方法存在于Array原型中。


12

实际上,如果您不喜欢for标题中的声明,则可以执行以下操作:

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

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


9

在声明循环变量的位置使用var。隐式声明的变量具有不同的范围,可能不是您想要的。


9
for(var i = 0; ...)

是一种常见的模式,但与

for(int i; ...)

在C ++中,变量没有作用于for块。实际上,将vargets提升到封闭范围(函数)的顶部,以便ifor循环之前(当前范围/函数的开始之后)和之后都可以有效地使用局部变量。

换句话说,请执行以下操作:

(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 中用varor let或or 声明的局部变量const)而不是隐式全局变量。

for(i=0; ...)否则for(i in ...)会失败,如果您使用"use strict";(应按要求使用)i且未声明。



4

我认为var出于性能方面的考虑是好的。

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


3

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

如果您打算在for循环中使用loop的索引,而其他行将不需要使用该索引,则最好使用“ var”声明该变量,这样您就可以确保“ x”是for循环的索引以0初始化,而另一个,如果在此上下文中有其他“ x”变量可用,则该变量将被循环的索引覆盖-也就是说,您将遇到一些逻辑错误-。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.