It would seem that nested forEach is very much faster, as this jsPerf shows:
Setup:
const modules = Array(30).fill({courses:Array(30).fill(1)}) //30x30 elements
let deleteCourses = [];
Case 1: nested forEach - 29,293 ops/sec
modules.forEach((mod) => {
mod.courses.forEach((course) => {
deleteCourses.push(course);
})
})
Case 2: ES6 Spread Operator - 49.13 ops/sec
modules.forEach((mod) => {
deleteCourses = [...deleteCourses, ...mod.courses];
})
That's about 600x faster for that 30x30 sample
This makes sense when you consider the amount of redundancy in respreading deleteCourses
on every iteration. In contrast to nested forEach, the number of addition operations performed per iteration is about the length of deleteCourses
for that iteration. That number is also growing on every iteration.
So the difference in performance has little to do with the creation of new Array
instances, and much to do with the multitude of redundant steps created by this misusage of the spread operator.
To be sure, looking at the two cases individually, we can see that:
- the ES6 Spread Operator algorithm is exponential:
O(2^n)
- the nested forEach algorithm is linear:
O(n)