JavaScript“for-in”循环中的“var”还是没有“var”?
Posted
技术标签:
【中文标题】JavaScript“for-in”循环中的“var”还是没有“var”?【英文标题】:"var" or no "var" in JavaScript's "for-in" loop? 【发布时间】:2011-08-08 16:42:30 【问题描述】:在 javascript 中编写for-in
循环的正确方法是什么?浏览器不会对我在这里展示的两种方法中的任何一种提出投诉。首先,有一种方法是显式声明迭代变量x
:
for (var x in set)
...
另外,这种读起来更自然但对我来说似乎不正确的方法:
for (x in set)
...
【问题讨论】:
在解决为什么 webpack 生成的捆绑文件在 for 循环中导致错误时遇到了这篇文章,其中var
未用于声明迭代器 i
:Uncaught ReferenceError: i is not defined
。所以我将从现在开始使用它:/ webpack 奇怪地对待“全局”变量,更多信息请参见:***.com/a/40416826
【参考方案1】:
我总是使用 ES2015 中引入的 let
块作用域。
for (let x in set)
...
Additional reading and examples
【讨论】:
【参考方案2】:你真的应该用var
声明局部变量,always。
您也不应该使用“for ... in”循环,除非您完全确定这是您想要做的。对于遍历真实数组(这很常见),您应该始终使用带有数字索引的循环:
for (var i = 0; i < array.length; ++i)
var element = array[i];
// ...
使用“for ... in”遍历普通数组可能会产生意想不到的后果,因为您的循环可能会获取数组的属性而不是数字索引的属性。
edit — 在 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 原型中。
【讨论】:
在区分 Object for/in 循环与 Array for/length 循环方面,最好让您更清楚地使用 Array.forEach()
方法。【参考方案3】:
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 中)声明的变量)而不是隐式全局变量。
如果您使用"use strict";
(应该如此)并且未声明i
,for(i=0; ...)
或for(i in ...)
将失败。
【讨论】:
【参考方案4】:使用var
是最干净的方式,但两者都按照此处所述的方式工作:https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
基本上,通过使用var
,您可以确保创建一个新变量。否则你可能会不小心使用了之前定义的变量。
【讨论】:
【参考方案5】:其实,如果你不喜欢 for
标题中的声明,你可以这样做:
var x;
for (x in set)
...
正如该问题的其他答案所述,完全不使用 var
会产生不必要的副作用,例如分配全局属性。
【讨论】:
【参考方案6】:从一般的角度来看,第一个版本将用于必须存在于循环范围内的索引,而另一个版本将是调用循环构造函数的范围内的任何变量。
如果你打算在 for 循环中使用循环的索引,而下一行中的其他人不需要这样做,最好用“var”声明变量,这样你就可以确定“x”是 for 循环的索引已初始化使用 0,而另一个,如果在此上下文中可以使用其他“x”变量,这将被循环的索引覆盖 - 那就是你会有一些逻辑错误 -。
【讨论】:
【参考方案7】:使用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 Scoping and Hoisting
【讨论】:
不回答问题,这是正常的for循环,不是for in。 i==5 的原因不是因为提升而不是 for 循环中缺少 var 吗? 另一个重要方面是严格模式禁止隐式创建全局属性,因此使用标准的“for in”循环而没有 var 语句实际上会失败并返回 ReferenceError。 但是,来自 Java,将var
放入 for
头部看起来就像它在 for 循环中是本地的,但它不是。因此,我更喜欢下面user422039的风格。
如果你碰巧在一个范围内有多个 for 循环怎么办?您要么必须重用索引(无 var),要么必须声明大量新变量(j、k、l、m、...),这些变量将永远不会再使用。【参考方案8】:
第一个版本:
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
。你不想要那个!在 for
循环中使用 var x
。
最重要的是:如果for
循环在全局范围内(即不在函数中),那么本地范围(如果您使用var x
,则在其中声明范围x
)是与全局作用域相同(如果使用不带 var 的 x
,则隐式声明作用域 x
),因此两个版本将相同。
【讨论】:
最后是一个完整的答案,带有解释和很好的例子。它确实回答了这个问题。【参考方案9】:我认为 var 出于性能原因是好的。
Javascript 不会查看整个全局范围来查看 x 是否已经存在于其他地方。
【讨论】:
【参考方案10】:使用用var
声明循环变量的那个。隐式声明的变量具有不同的范围,这可能不是您想要的。
【讨论】:
以上是关于JavaScript“for-in”循环中的“var”还是没有“var”?的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript 中的 for 循环---------------引用
javascript for-for vs for-in循环
JavaScript里的循环方法:forEach,for-in,for-of