This SonarQube rule is yet another arbitrary improvement. Do you think they have a committee or any kind of workflow to approve the inclusion of a “Clean Code” rule? I guess not.
Using
forEach
instead offor…of
can lead to:
- Performance degradation, especially with large arrays due to function call overhead
- Limited control flow capabilities, preventing early exits and iteration skipping
- Type safety issues in TypeScript where type narrowing is lost across function boundaries
- Reduced code maintainability due to less intuitive syntax for simple iterations
Performance degradation, especially with large arrays due to function call overhead
The first point should the the most relevant, right? But it is the most dubious.
Here is a small program to measure function call overhead in JavaScript:
const a = (x) => 2*x
const b = (x) => a(x)
measure = (fn, n) => {
const time1 = new Date()
for (let i = 0; i < n;, i++) {
fn(i)
}
const time2 = new Date()
return time2 - time1
}
console.log(measure(a, 1_000), 'ms') // 0 ms
console.log(measure(a, 1_000_000), 'ms') // 4 ms
console.log(measure(b, 1_000_000), 'ms') // 11 ms
// using Node 24.8.0 + MacBook Air M4
- a is a function that returns a native computation
- b is a function that returns the result of a function call (to get the same native computation)
Thus, the difference between a and b is just one additional function call.
Is it worth to refactor my working .forEach
loop to a new for...of
loop to save 7 milliseconds on an array of a million items? Definitely not!