为什么JavaScript的For ... In循环不推荐用于数组?

时间:2011-03-11 06:35:56

标签: javascript for-in-loop

我在某个地方读了(抱歉,我找不到链接),不推荐For ... In循环用于数组。这里说:http://www.openjs.com/articles/for_loop.php表示关联数组,http://www.w3schools.com/js/js_loop_for_in.asp表示迭代对象的所有属性(不说它可以在数组上使用)。我不知道该相信谁。我不希望这个问题成为辩论。我只是想知道我是否可以在我的代码中使用它而没有不可预见的副作用。谢谢!

4 个答案:

答案 0 :(得分:20)

数组是一个对象,数组元素只是将数字索引转换为字符串的属性。例如,arr [123]引用数组对象arr中的属性“123”。

for ... in构造适用于所有对象,而不仅仅是数组,这是造成混淆的原因。

当有人for ... in数组时,程序员通常只迭代所有元素,甚至很可能按顺序 >。例如,如果数组包含一堆数字,那么程序员很可能打算迭代一个数字流。语义与其他编程语言中的数组迭代非常相似,很容易混淆。

在JavaScript中,此构造不会按顺序迭代数组元素。它迭代所有数组的属性名称(包括继承的原型函数的名称,添加到它的任何属性,添加到它的任何其他非元素属性等),并且不按顺序排列所有。在早期的浏览器中,它甚至会找到属性length,尽管在最近的浏览器中,这些属性现在被定义为隐藏在这个原因中 - 人们不断绊倒它!

使用上面的整数数组,您不会得到数字流,而是一串文本字符串。而不是元素值,而是属性的名称(它们只是不以任何顺序排列的数字索引)。如果他/她来自另一种编程语言,这很可能程序员的意思。如果存储在数组中的元素恰好是相似的数值,那么它会让每个人都感到困惑。

这就是你不应该这样做的原因。你不应该使用看起来像它做一些明显的事情的语言结构,但实际上做的事情是完全不同的。它会产生非常模糊且很难找到的错误。

答案 1 :(得分:2)

我在几个浏览器(FireFox 3,Opera 9,IE6,IE9 beta,Chrome)中测试了数组迭代,它运行良好;我似乎记得一些跨浏览器的不兼容性,但我必须弄错。

但仍有一点需要注意:

正如您所提到的,for ... in语法用于迭代对象的属性;因此,对于数组,该数组对象的所有属性也将与元素一起迭代。通常,数组对象只具有与其中的键对应的属性,但如果另一个脚本修改Array.prototype(例如某个框架),则添加的方法/属性也会在迭代中意外显示。

答案 2 :(得分:2)

Prototype.js库文档中给出了几个很好的理由: http://www.prototypejs.org/api/array

基本上,使用for ... in迭代一个数组是很脆弱的,因为任何其他代码都可以为Array原型添加属性,然后它将成为每个数组对象的可枚举属性。

答案 3 :(得分:0)

使用for(... in ...)迭代数组不会获得数字键,它会获得字符串值。

它将为您提供在原型上定义的属性,因此如果任何代码扩展Array,例如通过做:

Array.prototype.each = ...;

然后您将看到属性each

没有任何人会以数组索引顺序获取属性。例如。尝试迭代

var arr = []
arr[1] = 1;
arr[0] = 0;

在很多浏览器上,您会在1之前获得0

并且您无法保证获得所有指数。尝试迭代

[0,,,3]

您将无法获得索引12