使用for...in
迭代数组并不保证顺序,但ES6引入了新的构造for...of
。
我对for...of
实现的有限测试表明它在数组上按顺序迭代,但这个属性是否有保证?
答案 0 :(得分:22)
使用
for...in
迭代数组不保证顺序,但ES6引入了新的构造for...of
。我对
for...of
实现的有限测试表明它在数组上按顺序迭代,但这个属性是否有保证?
是的,数组for-of
的顺序由array iterator definition保证:它将以数字索引顺序访问数组中的条目(包括那些不存在的条目,例如那些稀疏数组 - 或者应该是稀疏数组中的不 :-)):
Babel,这里是使用最新浏览器的网站摘要:
"use strict";
let a = [];
a[3] = 'd';
a[0] = 'a';
a.foo = "f";
for (let v of a) {
console.log(v);
}
输出:
a undefined undefined d
(两个undefined
在Babel的REPL中显示为空白。)
上面有两点需要注意:
即使数组具有可枚举的属性foo
,也不会访问它。
数组稀疏,for-of
访问不存在的两个条目(索引1和2)。
for-in
不有保证订单,即使在ES2015(又名“ES6”)中也没有。阅读规范是非常容易 ,但事实并非如此;有关详细信息,请参阅this answer。另请注意,在数组上使用for-in
不仅会访问数组的“索引”,还会访问数组的可枚举属性名称的 all ,包括非索引属性名称。例如,即使在ES2015中,也是如此:
"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);
}
......可能输出:
0 3 foo bar
...或
foo bar 0 3
......或其他东西,虽然很可能使用当前的JavaScript实现集(但规范不要求),所有数字键(“索引”)将被组合在一起,在之前或之后其他财产。
假设Array.prototype
或Object.prototype
上没有可枚举的属性(默认情况下没有)。如果有,我们也会看到它们。
如果你想遍历一个数组的值,for-of
是一个很好的工具,从ES2015开始,还有其他有用的工具,如Array#forEach
({{1}在稀疏数组上特别方便;它会跳过不存在的条目)。 forEach
很少是一个不错的选择。 this other answer中有一个详尽的选项列表。
答案 1 :(得分:5)
我对
for...of
实现的有限测试表明它在数组上按顺序迭代,但这个属性是否有保证?
是。但追求它有点复杂,因为for of
不会迭代数组(如for in
枚举对象)。相反,它通常按照各自的迭代器提供的顺序迭代所有可迭代对象。
实际上,数组是可迭代的,当从它们获取迭代器时,它将是一个迭代器,它以与在数组中找到的顺序相同的顺序产生数组的所有元素。您可以阅读spec for ArrayIterator
objects,它们基本上像for (var index=0; index<array.length; index++) yield array[index];
循环一样工作。
答案 2 :(得分:2)
根据for..of
的ES6规范for ( LeftHandSideExpression of AssignmentExpression ) Statement
如果LeftHandSideExpression是ObjectLiteral或 ArrayLiteral和词法标记序列匹配的 可以解析LeftHandSideExpression,不使用任何令牌 AssignmentPattern作为目标符号,则以下规则不是 应用。相反,AssignmentPattern的早期错误规则是 使用
根据这个语法规则定义,for..of循环将以令牌的词汇顺序执行,当它是数组或对象文字。
以下是David Walsh http://davidwalsh.name/es6-generators的一个很好的博客链接,他在这里通过示例解释了for..of
循环如何使用迭代器。