JavaScript performance tips - Arrays - map() vs. forEach()

·

3 min read

Introduction

In JavaScript, arrays come with a bunch of handy methods and tools to manipulate them.

Arrays are a great way to manipulate large amounts of data, quickly and easily.

However, with great powers comes great responsibilities.

Manipulating a large amount of data can come at performance costs if you are not careful

When should you worry about performance

Unless you are working on a project where performance is critical, I would not worry too much about performance until it becomes an issue.

For example, maybe you are developing a live trading application. Every millisecond counts for that application since a small latency can cause a large loss. In that case, performance might be the #1 priority for the developer.

In any other case, performance is not your priority. A great UX, a good looking UI can go a long way in making your application appear 'performant'. A few milliseconds won't make up for a poorly designed user interaction.

In the same way, if the performant solution comes at a cost of increased complexity, it might not be worth it. Using declarative programming over imperative programming provides a nicer developer experience (DX) and reduces complexity - which in turn reduces the chances of bugs.

Everything is a tradeoff, and often performance is not where you get the best bang for your buck.

However, if you notice that your application is suffering from a performance bottleneck affecting the user experience, then it might be time to optimise and solve that bottleneck.

Having said that,it is always a good idea to go for the low hanging fruits in performance. If writing performant code doesn't come at any cost if it doesn't add complexity and you don't have to sacrifice anything for it, then why not do so?

For example, if you wish to apply a transformation to an array of items, you have multiple options. Among them, there are two nice, concise and simple declarative ways of doing so: map() and forEach(). If one is better than the other, then why shouldn't use the better one?

Let's discuss this in the next point.

Applying a transformation to array items: map() vs. forEach()

Among our popular options to apply a transformation to items in an array, we have two main contestants: map() and forEach.

The main difference is mutability: forEach will mutate your array, while map will create a new array and leave your original array intact.

Because of that difference, you can probably guess that map() will be slower, since it does an extra operation (creating a new array).

Using JsBench, we obtain the following result when applying multiplication to an array of 1,000,000 numbers.

// Fill an array of 1,000,000 items with a random number
const array = Array(1_000_000).fill(Math.random())

// map()
array.map(item => item * 2)

// forEach()
array.forEach(item => item * 2)

js array performance map vs foreach.png

☝️ You can find their documentation on the great MDN website: here for forEach() and here for map()

Conclusion

As you can see, map() is 40% slower than forEach().

So we should always use forEach() right?

Not necessarily. As explained above, the comparison is unfair. map() does an extra step: it creates a new array. If we wanted to compare the true performance of these two, we would need to create an array with forEach() as well.

But it defeats the purpose: the point is use the right tool for the job.

  1. if you wish to mutate an array, use forEach(). It's faster.
  2. if you wish to not mutate your array, use map() and create a new array.

So next time you need to manipulate an array, think about mutability. You could be missing an easy performance optimisation by using map() if you don't need a new array.