【问题标题】:Does "for...of" loop iteration follow the array order in JavaScript?“for...of”循环迭代是否遵循 JavaScript 中的数组顺序?
【发布时间】:2015-06-11 05:54:30
【问题描述】:

使用 for...in 遍历数组并不能保证顺序,但是 ES6 引入了一个新的构造 for...of

我对@9​​87654323@ 实现的有限测试表明它确实在数组上按顺序迭代,但是这个属性是否得到保证?

【问题讨论】:

    标签: javascript for-loop ecmascript-6


    【解决方案1】:

    使用 for...in 遍历数组并不能保证顺序,但是 ES6 引入了一个新的构造 for...of

    我对@9​​87654327@ 实现的有限测试表明它确实在数组上按顺序迭代,但是这个属性是否得到保证?

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

    Live ExampleBabel 的 REPL 上,这里有一个现场 sn-p 供那些使用最新浏览器的人使用:

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

    输出:

    一种 不明确的 不明确的 d

    (两个undefineds 在 Babel 的 REPL 中显示为空白。)

    上面有两点需要注意:

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

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

    for-in,然而,not did 在 ES2015(又名“ES6”)到 ES2019 中没有保证顺序;在 ES2020 中,它遵循与 ES2015 中添加的顺序服从机制(Object.getOwnPropertyNames 等)相同的属性顺序(有一些警告)。考虑这个例子:

    "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);
    }

    在 ES2015 到 ES2019 中,它可能会输出

    0 3 富 酒吧

    富 酒吧 0 3

    或者别的什么。但是,从 ES2020 开始,它被指定为输出

    0 3 富 酒吧

    因为它必须首先按数字顺序访问 integer index 属性(名称为标准数字形式的字符串的属性),然后按 creation 顺序访问其他属性(所以,foobar 之前)。

    (假设Array.prototypeObject.prototype 上没有可枚举的属性(默认情况下没有)。如果有,我们也会看到它们,但没有指定在哪里。)

    如果你想循环遍历数组的for-of 是 ES2015 的一个很好的工具,以及其他有用的工具,例如 Array#forEachforEach 在稀疏时特别方便数组;它会跳过不存在的条目)。 for-in 很少是一个好的选择。 this other answer 中有详尽的选项列表。

    【讨论】:

      【解决方案2】:

      我对@9​​87654322@ 实现的有限测试表明它确实在数组上按顺序迭代,但是这个属性是否得到保证?

      是的。但是寻找它有点复杂,因为for of 不仅迭代数组(就像for in 确实枚举对象)。相反,它通常迭代所有 iterable 对象 - 按照它们各自的迭代器提供的顺序。

      事实上,数组就是这样一个可迭代的,当从它们获取迭代器时,它将是一个迭代器,它产生数组中所有元素的顺序与它们在数组中的顺序相同。您可以阅读spec for ArrayIterator objects,它们基本上就像for (var index=0; index<array.length; index++) yield array[index]; 循环一样工作。

      【讨论】:

        【解决方案3】:

        根据for..of 的 ES6 规范

        for ( LeftHandSideExpression of AssignmentExpression ) Statement
        

        如果 LeftHandSideExpression 是 ObjectLiteral 或 ArrayLiteral 和如果词法标记序列匹配 LeftHandSideExpression 可以在不使用任何标记的情况下进行解析 AssignmentPattern 作为目标符号,则以下规则不适用 应用。相反,AssignmentPattern 的早期错误规则是 用过。

        根据这个语法规则定义,当它是 ArrayObject Literal 时,for..of 循环将按照标记的词法顺序执行。

        这是 David Walsh http://davidwalsh.name/es6-generators 的一个不错的博客链接,他在其中举例说明了 for..of 循环如何使用迭代器工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-08
          • 2017-08-06
          • 2017-02-08
          • 2015-07-25
          相关资源
          最近更新 更多