简体   繁体   English

“for...of”循环迭代是否遵循 JavaScript 中的数组顺序?

[英]Does “for…of” loop iteration follow the array order in JavaScript?

Iterating over an array using for...in doesn't guarantee order, however ES6 introduces a new construct for...of .使用for...in迭代数组并不能保证顺序,但是 ES6 引入了一个新的结构for...of

My limited testing of implementations of for...of indicates that it does iterate in order on array, but is this property guaranteed?我对for...of of 实现的有限测试表明它确实在数组上按顺序迭代,但是这个属性是否有保证?

Iterating over an array using for...in doesn't guarantee order, however ES6 introduces a new construct for...of .使用for...in迭代数组并不能保证顺序,但是 ES6 引入了一个新的结构for...of

My limited testing of implementations of for...of indicates that it does iterate in order on array, but is this property guaranteed?我对for...of of 实现的有限测试表明它确实在数组上按顺序迭代,但是这个属性是否有保证?

Yes, the order of for-of on arrays is guaranteed by the array iterator definition : It will visit the entries in the array in numeric index order (including ones that don't exist, such as those in sparse arrays — or perhaps that should be those not in sparse arrays :-) ):是的,数组中for-of的顺序由数组迭代器定义保证:它将以数字索引顺序访问数组中的条目(包括不存在的条目,例如稀疏数组中的条目 - 或者可能应该不在稀疏数组中的那些:-)):

Live Example on Babel 's REPL, and here's an on-site snippet for those using an up-to-date browser: Babel的 REPL 上的实时示例,这是使用最新浏览器的用户的现场代码段:

 "use strict"; let a = []; a[3] = 'd'; a[0] = 'a'; a.foo = "f"; for (let v of a) { console.log(v); }

Output:输出:

a
undefined
undefined
d

(The two undefined s show as blank in Babel's REPL.) (这两个undefined在 Babel 的 REPL 中显示为空白。)

Two things to note above:以上两点需要注意:

  1. Even though the array has an enumerable property foo , it isn't visited.即使数组有一个可枚举的属性foo ,它也不会被访问。

  2. The array is sparse, and for-of did visit the two entries that aren't present (at indexes 1 and 2).该数组是稀疏的,并且for-of确实访问了两个不存在的条目(在索引 1 和 2 处)。

for-in , however, does not did not have a guaranteed order in ES2015 (aka "ES6") through ES2019; for-in ,然而,并不没有在ES2015(又名“ES6”)通过ES2019保证秩序; in ES2020, it follows the same property order (with some caveats) as the order-obeying mechanisms added in ES2015 ( Object.getOwnPropertyNames , etc.).在 ES2020 中,它遵循与 ES2015 中添加的顺序服从机制相同的属性顺序(有一些注意事项)( Object.getOwnPropertyNames等)。 Consider this example:考虑这个例子:

 "use strict"; var a = []; a.foo = "f"; a[3] = 'd'; a[0] = 'a'; a.bar = "b"; var key; for (key in a) { console.log(key); }

In ES2015 through ES2019, it might output在 ES2015 到 ES2019 中,它可能会输出

0
3
foo
bar

or或者

foo
bar
0
3

or something else.或者是其他东西。 As of ES2020, though, it is specified to output但是,从 ES2020 开始,它被指定为输出

0
3
foo
bar

because it has to visit the integer index properties first (properties whose names are strings in standard numeric form) in numeric order, followed by other properties in creation order (so, foo before bar ).因为它必须首先按数字顺序访问整数索引属性(名称为标准数字形式的字符串的属性),然后按创建顺序访问其他属性(因此, foobar之前)。

(That assumes there are no enumerable properties on Array.prototype or Object.prototype (by default there aren't). If there were, we'd see them as well, but it's not specified where.) (假设Array.prototypeObject.prototype上没有可枚举的属性(默认情况下没有)。如果有,我们也会看到它们,但没有指定在哪里。)

If you want to loop through an array's values , for-of is a great tool as of ES2015, alongside the other useful tools such as Array#forEach ( forEach is particularly handy on sparse arrays; it skips the entries that don't exist).如果你想遍历数组的for-of是 ES2015 的一个很好的工具,还有其他有用的工具,如Array#forEachforEach在稀疏数组上特别方便;它跳过不存在的条目) . for-in is rarely a good choice. for-in很少是一个好的选择。 There's an exhaustive list of options in this other answer .这个其他答案中有一个详尽的选项列表。

My limited testing of implementations of for...of indicate it does iterate in order on array, but is this property guaranteed?我对for...of of 实现的有限测试表明它确实在数组上按顺序迭代,但是这个属性是否有保证?

Yes.是的。 But hunting it down is a littlebit complicated, as for of doesn't only iterate arrays (like for in does enumerate objects).但是寻找它有点复杂,因为for of不仅迭代数组(就像for in枚举对象一样)。 Instead, it generically iterates all iterable objects - in the order that their respective iterator supplies.相反,它通常迭代所有可迭代对象——按照它们各自的迭代器提供的顺序。

In fact arrays are such an iterable, and when getting an iterator from them it will be an iterator that yields all elements of the array in the same order as they can be found in the array.事实上,数组是一种可迭代的,当从它们获取迭代器时,它将是一个迭代器,它以在数组中找到的相同顺序生成数组的所有元素。 You can read the spec for ArrayIterator objects , they basically work like a for (var index=0; index<array.length; index++) yield array[index];您可以阅读ArrayIterator对象规范,它们基本上像for (var index=0; index<array.length; index++) yield array[index]; loop.环形。

As per ES6 spec for for..of根据 ES6 规范for..of

for ( LeftHandSideExpression of AssignmentExpression ) Statement

If LeftHandSideExpression is either an ObjectLiteral or an ArrayLiteral and if the lexical token sequence matched by LeftHandSideExpression can be parsed with no tokens left over using AssignmentPattern as the goal symbol then the following rules are not applied.如果 LeftHandSideExpression 是 ObjectLiteral 或 ArrayLiteral,并且如果可以使用 AssignmentPattern 作为目标符号来解析与 LeftHandSideExpression 匹配的词法标记序列而没有剩余标记,则不应用以下规则。 Instead, the Early Error rules for AssignmentPattern are used.相反,使用了 AssignmentPattern 的早期错误规则。

As per this grammar rule definition a for..of loop will be executed in the lexical order of the tokens when it is an Array or Object Literal.根据此语法规则定义,当 for..of 循环是数组对象字面量时,将按标记的词法顺序执行。

Here is a nice blog link by David Walsh http://davidwalsh.name/es6-generators where he has explained with example how a for..of loop works using iterators.这是 David Walsh 的一个不错的博客链接http://davidwalsh.name/es6-generators ,他在其中举例说明了for..of循环如何使用迭代器工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM