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

发布于 2024-10-21 20:08:06 字数 396 浏览 1 评论 0原文

我在某处读到(抱歉,我找不到链接),不建议对数组使用 For...In 循环。这里说的是: http://www.openjs.com/articles/for_loop.php 它适用于关联数组,并且在 http://www.w3schools.com/js/ js_loop_for_in.asp 用于迭代对象的所有属性(并没有说它可以用于数组)。我不知道该相信谁。我不想让这个问题成为一场辩论。我只是想知道是否可以在我的代码中使用它而不会产生不可预见的副作用。谢谢!

I read somewhere (sorry, I can't find the link) that the For...In loop is not recommended for arrays. It is said here: http://www.openjs.com/articles/for_loop.php that it is meant for associative arrays, and in http://www.w3schools.com/js/js_loop_for_in.asp that is for iterating through all the properties of an object (It does not say that it can be used on arrays). I do not know who to believe. I don't want this question to become a debate. I just want to know if I could use this in my code without unforeseen side effects. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

缘字诀 2024-10-28 20:08:06

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

for ... in 构造适用于所有对象,而不仅仅是数组,这会导致混乱。

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

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

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

这就是为什么你不应该这样做。您不应该使用看起来做明显事情但实际上做完全不同事情的语言构造。它会产生非常隐蔽且很难发现的错误。

An array is an object, and array elements are simply properties with the numeric index converted to string. For example, arr[123] refers to a property "123" in the array object arr.

The for ... in construct works on all objects, not just arrays, and that is cause for confusion.

When somebody for ... in an array, most often the programmer intends to iterate just all the elements, even most likely in order. For example, if the array holds a bunch of numbers, then the programmer most likely intends to iterate a stream of numbers. The semantics is so similar to array iteration in other programming languages that it is very easy to get confused.

In JavaScript, this construct does not iterate array elements in order. It iterates all the array's property names (including the names of inherited prototype functions, any properties added to it, any other non-element properties added to it etc.), and not in order at all. In earlier browsers, it will even find the property length, although in recent browsers these properties are now defined to be hidden for this exact reason -- people keep tripping on it!

With the array of integers above, you get not a stream of numbers, but a stream of text strings. And not the element values, but the names of the properties (which are just the numeric indices not in any order). This is most likely not what the programmer means, if he/she comes from another programming language. If the elements stored in the array happen to be similar numeric values, it confuses the hell out of everybody.

That's why you shouldn't do it. You shouldn't use a language construct that looks like it does obvious things, but actually does things that are completely different. It creates bugs that are very obscure and very difficult to find.

饮惑 2024-10-28 20:08:06

我已经在多个浏览器(FireFox 3、Opera 9、IE6、IE9 beta、Chrome)中测试了数组迭代,它工作得很好;我似乎记得一些跨浏览器不兼容的情况,但我一定是弄错了。

但仍然有一个警告:

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

I've tested array iteration in several browsers (FireFox 3, Opera 9, IE6, IE9 beta, Chrome) and it works fine; I seem to recall some cross-browser incompatibility but I must be mistaken.

There is still a caveat though:

As you've mentioned, the for ... in syntax is used for iterating over the properties of an object; so, with an array, all the properties of that array object will also be iterated over along with the elements. Normally, the array object only has properties corresponding to the keys in it, but if another script modifies Array.prototype (e.g. some framework), then the added methods/attributes would unexpectedly show up in the iteration as well.

玩心态 2024-10-28 20:08:06

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

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

A couple of good reasons are given in the Prototype.js library documentation:
http://www.prototypejs.org/api/array

Basically, using for...in to iterate an array is brittle since any other code can add properties to the Array prototype, which will then become enumerable properties on every array object.

辞取 2024-10-28 20:08:06

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

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

Array.prototype.each = ...;

那么您将看到属性each

无法保证您将按数组索引顺序获取属性。例如,尝试迭代在

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

很多浏览器上,您将在 0 之前得到 1

并且不能保证您获得所有索引。尝试迭代

[0,,,3]

您将不会获得索引 12

Iterating over an array using for(... in ...) will not get you numeric keys, it gets you string values.

It will get you properties defined on the prototype, so if any code extends Array, e.g. by doing:

Array.prototype.each = ...;

then you will see the property each.

There is no gaurantee that you will get the properties in array index order. E.g. try iterating over

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

On a lot of browsers you will get 1 before 0.

And you are not guaranteed to get all indices. Try iterating over

[0,,,3]

you will not get the index 1 or 2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文