ES6中,当都能使用array.forEach()和for...of时,是否有使用array.forEach()的理由?

3

随着ECMAScript 2015(ES6)中引入了for..of,是否还有理由继续推荐使用稍旧的Array.prototype.forEach()

今天写在ES6中的很多代码都包含如下代码:

let sum = 0;
values.forEach((value) => {
    sum += value;
});

在几乎所有这些情况下,都可以使用等效的 for..of 循环代替:
let sum = 0;
for (let value of values) {
  sum += value;
}

这两种格式的更简洁版本:

values.forEach(value => sum += value);
for (let value of values) sum += value;
< p > for..of 格式不仅适用于 Array 对象,还适用于其他可迭代对象,并且更加高效。与 Array.prototype.map() 不同,.forEach() 也没有返回值,无法进行进一步的链接。

它可能在调用链的末尾更易读,因此更有用(如下面的示例),或者如果每个项目都应用于未知回调。除了这些边缘情况外,它是否应该被避免?

['1', '2', 3].map(Number)
             .forEach(value => sum += value)

@Rooster 由于for...of是ES6的特性,一些不稳定的浏览器都不支持这两个选项。 - ssube
对于普通程序员来说,“for of”和“forEach”基本上是一样的东西。另一方面,像往常一样,“for of”和“for in”循环在IE中没有支持,所以我建议暂时避免使用它们。 - ODelibalta
@ssube 他问的是有没有任何理由,而不是支持ECMAScript6的事情是否有理由 :) 当然,我想你的观点可能有些含蓄 ;P - Rooster
1
到目前为止,我几乎找不到任何使用forEach的用例(你知道,副作用是不好的),在ES6中它肯定不会更有用。 - Bergi
1个回答

5
最重要的区别在于你不能从forEach中跳出,除非抛出异常,使用异常来控制流程是不好的做法。
对于总是遍历所有元素的数组循环,for ... offorEach 几乎是等价的。然而,如果你有一个循环保证只会访问每个元素一次,你可以使用 mapreduce 来替换任何 for-each 结构,并使事情更具有功能性。
你的求和示例是一个很好的reduce示例。当你可以直接使用以下代码时,forEach 不是最佳选择:
let sum = values.reduce((sum, value) => sum + value, 0);

如果您想从数组中挑选元素,通常可以使用filter。对于流程控制,everysome可以使用,并根据需要进行反转(如评论中所述)。
一般来说,forEach通常可以被更具描述性和专业化的数组方法替换,除非您特别需要引起副作用。 for...of在可迭代对象方面非常有用,但不总是数组的最佳选择。

可能不是我这边最好的示例选择。您当然是正确的,指出应该在这里使用 reduce() - lyschoening
1
为了流程控制,可以使用.every()或.some()。 - lyschoening
1
@lyschoening:不,它真的不应该。如果你需要自定义控制流程,请使用循环并显式地使用“break”。请不要滥用“every”或“some”。 - Bergi
@Bergi MDN上关于.forEach()的文档建议将其用于此目的,这就是为什么我在这里提到它作为打破循环的替代方法。这不是我能想象自己写出来的东西。 - lyschoening
@Bergi,虽然你说的跳出循环可能对于复杂流程更好,但我认为在if语句中使用every或some作为条件也是非常合理的用例。 - ssube
@ssube:我并不是想表达其他意思 :-) 但我认为在条件语句中使用 every/some 不属于“流程控制”(循环的)。 - Bergi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接