我在某处读到(对不起,我找不到链接),不建议将 For...In 循环用于数组。这里说:http ://www.openjs.com/articles/for_loop.php它用于关联数组,而在http://www.w3schools.com/js/js_loop_for_in.asp用于迭代一个对象的所有属性(它并没有说它可以用于数组)。我不知道该相信谁。我不希望这个问题成为辩论。我只想知道我是否可以在我的代码中使用它而不会产生不可预见的副作用。谢谢!
4 回答
数组是一个对象,数组元素只是将数字索引转换为字符串的属性。例如,arr[123] 引用数组对象 arr 中的属性“123”。
该for ... in
构造适用于所有对象,而不仅仅是数组,这会引起混淆。
当某人for ... in
使用数组时,程序员通常打算只迭代所有元素,甚至最有可能按顺序迭代。例如,如果数组包含一堆数字,那么程序员很可能打算迭代一个数字流。语义与其他编程语言中的数组迭代非常相似,很容易混淆。
在 JavaScript 中,此构造不会按顺序迭代数组元素。它迭代数组的所有属性名称(包括继承的原型函数的名称、添加到其中的任何属性、添加到其中的任何其他非元素属性等),并且完全不按顺序。在早期的浏览器中,它甚至会找到 property length
,尽管在最近的浏览器中,这些属性现在被定义为隐藏的确切原因——人们一直在绊倒它!
使用上面的整数数组,您得到的不是数字流,而是文本字符串流。而不是元素值,而是属性的名称(它们只是数字索引,没有任何顺序)。如果他/她来自另一种编程语言,这很可能不是程序员的意思。如果存储在数组中的元素恰好是相似的数值,那么每个人都会感到困惑。
这就是为什么你不应该这样做。您不应该使用一种看起来像是在做显而易见的事情,但实际上却在做完全不同的事情的语言结构。它会创建非常模糊且很难找到的错误。
我已经在几个浏览器(FireFox 3、Opera 9、IE6、IE9 beta、Chrome)中测试了数组迭代,它运行良好;我似乎记得一些跨浏览器不兼容,但我一定是弄错了。
但是仍然有一个警告:
正如您所提到的,该for ... in
语法用于迭代对象的属性。因此,对于数组,该数组对象的所有属性也将与元素一起迭代。通常,数组对象只有与其中的键对应的属性,但如果另一个脚本修改Array.prototype
(例如某些框架),那么添加的方法/属性也会意外地出现在迭代中。
Prototype.js 库文档中给出了几个很好的理由:http: //www.prototypejs.org/api/array
基本上,使用 for...in 来迭代数组是很脆弱的,因为任何其他代码都可以向 Array 原型添加属性,然后这些属性将成为每个数组对象的可枚举属性。
使用迭代数组for(... in ...)
不会得到数字键,它会得到字符串值。
它将为您提供在原型上定义的属性,因此如果有任何代码扩展Array
,例如通过执行以下操作:
Array.prototype.each = ...;
然后你会看到属性each
。
无法保证您将按数组索引顺序获取属性。例如尝试迭代
var arr = []
arr[1] = 1;
arr[0] = 0;
在很多浏览器上你会得到1
之前的0
.
而且您不能保证获得所有索引。尝试迭代
[0,,,3]
你不会得到索引1
或2
.