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

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

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

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

 for (x in set) { ... } 

使用var ,它会减小variables的范围,否则variables将查找最近的查找var语句的闭包。 如果它找不到var那么它是全局的(如果你处于严格模式, using strict全局variables会引发错误)。 这可能会导致类似以下的问题。

 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的局部variables。 第二个版本:

 for (x in set) { ... } 

才不是。

如果x已经是一个局部variables(即,你有一个var x;var x = ...;在你当前的作用域(即当前函数)的早些时候),那么它们将是等价的。 如果x不是一个局部variables,那么使用第二个将会隐式地声明一个全局variablesx 。 考虑这个代码:

 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(); 

你可能会期望这个提醒你, thereheliheytherecopter ,但是因为x是一个一样的,它会提醒你, therethereheythere there 。 你不要那个! 在for循环中使用var x

最重要的是:如果for循环处于全局作用域(即不在函数中),则局部作用域(如果使用var x则声明范围var x )与全局作用域相同x在没有var的情况下使用x隐式声明),所以两个版本是相同的。

你真的应该总是var声明局部variables。

你也不应该使用“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声明循环variables的那个。 隐式声明的variables有一个不同的范围,可能不是你想要的。

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

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

 for(var i = 0; ...) 

是一个常见的模式,但它不同于

 for(int i; ...) 

在C ++中,variables不在作用域的范围内。 事实上, 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块。

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

for(i=0; ...)for(i in ...)将会失败,如果你使用"use strict"; (你应该), i没有宣布。

我认为var是有利于性能的。

Javascript不会查看整个全局范围,看看x是否已经存在。

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

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