我有以下函数
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
实例。
谢谢!
似乎嵌套的forEach要快得多,正如jsPerf所示:
设置:
const modules = Array(30).fill({courses:Array(30).fill(1)}) //30x30 elements
let deleteCourses = [];
案例1:嵌套的forEach-29293 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)