Use “for…of” loops instead of “forEach” method calls

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 of for…​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!