【问题标题】:Why would we need a new loop construct for-of in ES2015 when we already have for, forEach?为什么在 ES2015 中我们已经有了 forEach,我们还需要一个新的循环结构 for-of?
【发布时间】:2016-05-13 03:31:52
【问题描述】:

我理解这样一个概念:当我们使用循环迭代变量var i=0; i<length; i++ 时,我们总是希望避免循环的命令式方式,因为它是非常冗长和命令式的做事方式,即使我们不这样做,它也会为我们提供项目索引'不需要它们。数组上的.forEach() 方法似乎通过在声明性方法中公开val(和index 仅在需要时)来解决这个问题:

var arr = [1, 2, 3, 4];
arr.forEach(function (val) {
  // Use val
});

我正在浏览 ES6 结构并看到了新的 for-of 循环结构。试用后我的问题是:

既然我们已经在语言中定义了 2,为什么还需要一个新的构造?它实现了哪些功能是上述 2 个循环构造无法实现的?

【问题讨论】:

  • 为了一致地迭代可迭代对象,一方面。
  • for..of 与(可能)无限序列生成器一起使用。 .forEach() 无法做到这一点。
  • for 循环并不冗长。我也会对您将forEach 描述为“声明性”提出异议;它是(适度的)“功能性的”,但仍然完全是程序性/必要性的。一个小问题,但for...of中的变量可以解构,所以你可以写for ([a, b] of pairs)。
  • forEach 是违反直觉的——如果没有其他原因的话——那就是。

标签: javascript for-loop foreach ecmascript-6


【解决方案1】:

forEach 存在于 Array.prototype 上,但数组不是我们迭代的唯一类型。 ES6 引入了许多其他方法,for...of 也提供了一种一致的方式来实现自定义类型的迭代行为。

【讨论】:

    【解决方案2】:

    既然我们已经在语言中定义了 2,为什么还需要一个新的构造?它实现了哪些功能是上述 2 个循环构造无法实现的?

    您可以为 ES2015 中的许多新功能提出这样的论点。箭头函数、let、rest 参数、解构等或多或少只是你已经可以在 JS 中做的事情的语法糖。像 Babel 这样将 ES2015 转换为 ES5 的工具证明了这一点。

    那么,语法糖的意义何在?为了减少样板代码并让工程师专注于代码应该做什么,而不是如何它应该做什么。


    如前所述,for...of 适用于任何可迭代(任何实现了返回迭代器的[Symbol.iterator] 方法的东西),而不仅仅是数组。数组也是可迭代的。

    for...of 并没有真正引入现有语法(afaik)无法完成的任何事情。您可以使用带有 while 循环的迭代器。

    for (var foo of bar) {
      // ...
    }
    

    相当于

    var it = bar[Symbol.iterator](), next;
    while ((next = it.next()).done !== false) {
      var foo = next.value;
      // ...
    }
    

    但是,这并不容易理解(或编写)。如果我们假设迭代器应该变得更流行/普遍,那么更好地支持使用迭代器似乎是合理的。

    【讨论】:

    • 所以,故事的要点是 ES6 有多种类型的集合/可迭代对象,例如 Maps、Sets、Generators,并且使用 for-of 更容易使用迭代器。对吗?
    • 太棒了。非常感谢:)
    【解决方案3】:

    原因更多是为了方便而不是添加任何新功能。我在 Github 的 Notes repo 中写过这个。我这里直接解释一下:

    在 ES5 之前,for 循环是这样写的:

    for (var i = 0; i < arr.length; i++) {
        // Do something
    }
    

    在 ES5 中,我们可以这样写:

    arr.forEach(function(elem) {
        // Do something
    });
    

    前者的优点是我们可以在中间跳出循环。 后者的优点是简洁。 ES6 将它们结合起来并引入了称为 for-of 的新语法:

    for (let elem of arr) {
        // Do something
    }
    

    【讨论】:

    • 我几乎完全不同意。这根本不是为了方便。它是关于支持 ES6 中可迭代的整个概念。另外,我不会说forEach 的优点是简洁(至少不是唯一的)。那么,你的最后一个例子是错误的——这根本不会像你想象的那样起作用。使用for..of 维护索引的唯一方法是自己维护它。
    • @torazaburo,您对索引部分是正确的。我一定是误会了。我会删除它。
    猜你喜欢
    • 2017-11-13
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 2010-11-20
    相关资源
    最近更新 更多