The difference is that the forEach
closure is writing to a bound variable. If you do the same thing in the for
loop, it gets slow, too:
{ console.time('for 1') let sum = 0 for (let i = 0; i < data.length; i++) { sum += data[i] * data[i]; } console.timeEnd('for 1') } { console.time('for 2') let sum = 0 for (let i = 0; i < data.length; i++) { sum += data[i] * data[i]; } console.timeEnd('for 2') function foo() { sum = 1; } // create a closure bound to sum; note we never even call this }
Result:
for 1: 31.060ms for 2: 789.796ms
Note that the loops are identical. The only difference is that in the second block, we've bound sum
to a closure. That makes writing to it much more expensive.
That's why your forEach
loop is so much slower. It's the only code in your example that writes to a bound variable inside the loop. You'd get the same performance degradation in any of your other looping constructs if you do the same thing.