ES6传播元素与嵌套forEach性能

时间:2017-11-14 00:57:06

标签: performance ecmascript-6

我有以下功能

const modules = [{courses:[...]},{courses:[...]},...]
const deleteCourses = [];
modules.forEach((mod) => {
    mod.courses.forEach((course) => {
        deleteCourses.push(course));
    }
    // versus
    deleteCourses = [...deleteCourses, ...mod.courses];
});

假设模块和课程长度在30到100之间,我想知道哪一个更有效率?

一方面,我被教导要避免嵌套forEach循环。另一方面,数组文字每次都会创建一个新的Array实例。

谢谢!

1 个答案:

答案 0 :(得分:3)

似乎嵌套forEach 非常快,因为jsPerf显示:

设置:

const modules = Array(30).fill({courses:Array(30).fill(1)}) //30x30 elements
let deleteCourses = [];

案例1:嵌套forEach - 29,293 ops / sec

modules.forEach((mod) => {
    mod.courses.forEach((course) => {
        deleteCourses.push(course);
    })
})

案例2: ES6点差操作员 - 49.13操作/秒

modules.forEach((mod) => {
    deleteCourses = [...deleteCourses, ...mod.courses];
})

对于30x30样本来说,这个速度提高了600倍

在考虑每次迭代时重新扩展deleteCourses的冗余量时,这是有意义的。与嵌套的forEach 相比,每次迭代执行的加法运算的数量大约是该迭代的deleteCourses的长度。这个数字在每次迭代中都在增长。

因此,性能上的差异与创建新的Array实例几乎没有关系,而且与扩散运算符的这种误用造成的大量冗余步骤有很大关系。

可以肯定的是,单独看两个案例,我们可以看到:

  • ES6 Spread Operator 算法呈指数级:O(2^n)
  • 嵌套forEach 算法是线性的:O(n)