"var”;或者没有”;var”;在JavaScript's”;在“;环

"var" or no "var" in JavaScript's "for-in" loop?

本文关键字:var quot 或者 JavaScript      更新时间:2023-09-26

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

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

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

for (x in set) {
    ...
}

使用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范围界定和提升

第一个版本:

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。你不想那样!在for循环中使用var x

最重要的是:如果for循环在全局作用域中(即不在函数中(,则本地作用域(如果使用var x,则在中声明作用域x(与全局作用域(使用不带var的x,则在中隐式声明作用域x(相同,因此两个版本将相同。

您确实应该用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原型上。

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

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

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

使用声明循环变量var的方法。隐含声明的变量具有不同的作用域,这可能不是您想要的。

for(var i = 0; ...)

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

for(int i; ...)

在C++中,变量的作用域不是CCD_ 41块。事实上,var被提升到封闭作用域(函数(的顶部,因此本地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块。

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

如果使用"use strict";(应该使用(并且未声明i,则for(i=0; ...)for(i in ...)将失败。

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

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

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

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

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

如果您要在for循环内部使用循环的索引,而其他人在接下来的行中不需要这样做,那么最好用"var"声明变量,这样您就可以确保"x"是用0初始化的for循环索引,而另一个,如果其他"x"变量在该上下文中可用,则它将被循环的索引覆盖-也就是说,您会有一些逻辑错误-。

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

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

附加阅读和示例