Why is JavaScript's For…In loop not recommended for arrays?
我在某个地方读到(抱歉,我找不到链接),不建议数组使用for…in循环。这里说:http://www.openjs.com/articles/for ou loop.php它是用于关联数组的,在http://www.w3schools.com/js/js ou loop ou for ou in.asp中它是用于迭代对象的所有属性(它没有说它可以用于数组)。我不知道该相信谁。我不想把这个问题变成辩论。我只是想知道我是否可以在代码中使用它,而不会产生不可预见的副作用。谢谢!
数组是一个对象,数组元素只是将数字索引转换为字符串的属性。例如,arr[123]引用数组对象arr中的属性"123"。
当有人使用一个数组时,程序员通常只打算迭代所有元素,甚至最有可能是按顺序迭代。例如,如果数组包含一组数字,那么程序员很可能打算迭代一个数字流。语义与其他编程语言中的数组迭代非常相似,因此很容易混淆。
在JavaScript中,此构造不会按顺序迭代数组元素。它迭代数组的所有属性名(包括继承的原型函数的名称、添加到它的任何属性、添加到它的任何其他非元素属性等),并且完全不按顺序进行。在早期的浏览器中,它甚至可以找到
使用上面的整数数组,您得到的不是数字流,而是文本字符串流。而不是元素值,而是属性的名称(只是数字索引,而不是任何顺序)。如果程序员来自另一种编程语言,这很可能不是程序员的意思。如果存储在数组中的元素恰好是相似的数值,它会把所有人都搞糊涂。
所以你不应该这样做。你不应该使用一个看起来很明显的语言结构,但实际上它会做一些完全不同的事情。它会产生非常模糊和很难找到的错误。
在prototype.js库文档中给出了几个很好的理由:http://www.prototypejs.org/api/array
基本上,使用for…in迭代数组是很脆弱的,因为任何其他代码都可以向数组原型添加属性,然后这些属性将成为每个数组对象的可枚举属性。
我已经在几个浏览器(火狐3、Opera 9、IE6、IE9测试版、Chrome)中测试了数组迭代,它工作得很好;我似乎还记得一些跨浏览器的不兼容性,但我一定搞错了。
不过,还有一个警告:
如前所述,
使用
它将在原型上为您定义属性,因此如果任何代码扩展
1 | Array.prototype.each = ...; |
然后您将看到
没有Gaurantee可以按数组索引顺序获取属性。例如,尝试迭代
1 2 3 | var arr = [] arr[1] = 1; arr[0] = 0; |
在很多浏览器中,你会在
你不一定能得到所有的指数。尝试重复
1 | [0,,,3] |
您将无法获得索引