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

时间:2015-04-06 19:13:17

标签: javascript for-loop ecmascript-6

使用for...in迭代数组并不保证顺序,但ES6引入了新的构造for...of

我对for...of实现的有限测试表明它在数组上按顺序迭代,但这个属性是否有保证?

3 个答案:

答案 0 :(得分:22)

  

使用for...in迭代数组不保证顺序,但ES6引入了新的构造for...of

     

我对for...of实现的有限测试表明它在数组上按顺序迭代,但这个属性是否有保证?

是的,数组for-of的顺序由array iterator definition保证:它将以数字索引顺序访问数组中的条目(包括那些不存在的条目,例如那些稀疏数组 - 或者应该是稀疏数组中的 :-)):

Live Example的REPL上的

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中显示为空白。)

上面有两点需要注意:

  1. 即使数组具有可枚举的属性foo,也不会访问它。

  2. 数组稀疏,for-of 访问不存在的两个条目(索引1和2)。

  3. 然而,

    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.prototypeObject.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循环如何使用迭代器。