Refactoring every .forEach to a .map
Tags: javascript, codequality
Published: 2020-09-25 16:19:35

---
title: Refactoring every .forEach to a .map
published: true
description: A comparison between JavaScript's forEach and map functions, plus a refactor
tags: javascript, codequality
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/tf2ql066iofqtdbuk7s0.jpg
---

I often read JavaScript articles and noticed that many of them focus heavily on `map`, `filter` and `reduce`, more so than other array methods. In my current React project, I noticed that I've used `map` more but also that I unconsciously used `forEach` a bunch of times, so I decided to dig into it more.

First, let's go over what we know about the two functions.

## `.forEach`

* Goes over the array it is called on and executes the callback function on each element
* Changes the original array
* Returns undefined

```javascript
// MDN's example

const array1 = ['a', 'b', 'c'];

array1.forEach(element => console.log(element));

// expected output: "a"
// expected output: "b"
// expected output: "c"
```

## `.map`

* Goes over the array it is called on and executes the callback function on each element
* Does not change the original array
* Returns a new array with the result

```javascript
// MDN's example

const array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]
```

As we saw, both functions **do the exact same thing**, and both are supported in all browsers. However, the way they work under the hood differs. 

## Differences

### 1. Use cases

`map` returns a new array without mutating the original, so it makes sense to use it if we are planning to use the returned array elsewhere. However, if we don't mind mutating the original array and aren't planning to use it somewhere else, using `forEach` is recommended. Per [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#When_not_to_use_map): 

> You shouldn't be using `map` if you're not using the array it returns and/or you're not returning a value from the callback.

### 2. Approach

Because of `map`’s nature, people who prefer a more functional approach will lean towards it. Functional programming is an approach to building software by using pure functions that take an input and return an output. In functional programming, functions do not modify variables outside of their scope, state is not shared and data is never mutated. This approach greatly diminishes the number of bugs that may be introduced into your application.

### 3. Performance

According to [this](https://codeburst.io/javascript-map-vs-foreach-f38111822c0f?gi=d9973392feeb) post, `map` seems to be much more performant than `forEach`. However, I've since learned there's a big deal of controversy around this particular benchmark. It's not fair to compare the following two pieces of code

```javascript
arr.forEach((num, index) => {
    return arr[index] = num * 2;
});
```

```javascript
let doubled = arr.map(num => {
    return num * 2;
});
```

since the `return` statement in the first example serves no purpose. Moreover, the performance of these functions depends on the implementation of JavaScript engines in different browsers, so the comparison is not so cut-and-dried. 


### 4. Asynchronous programming
As stated by [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#forEach_expects_a_synchronous_function), `forEach` expects its callback to be synchronous, so it won't play well with any fancy async code you may have. `map` however will be more tolerant.


## Refactoring

In my project, I was using `forEach` to iterate over my rounds array, which looks like this:

```json
"rounds": [
{
    "artists": [
    {
        "name": "Three Days Grace",
    },
    {
        "name": "IDK",
    },
    ...
    ]
},
...
]
```

I have an array of strings that contains images of the current round's artists, and I wanted to iterate over each artist and add the image property to the object. This is how I first achieved that: 

```javascript
const artistImages = getArtistData(artistData); // returns an array of strings
rounds.forEach((round, index) => {
   round.artists[currentRound].image = artistImages[index];
});
return rounds;
```

I was calling this function in a component then assigning the returned array in state. Now, the state looked like this:

```json
"rounds": [
{
    ...
    "artists": [
    {
        "name": "Three Days Grace",
        "image": "https://i.scdn.co/image/2a9ec8d494f8d0a52fd67c3239efc2b9e79a4ced"
    },
    {
        "name": "IDK",
        "image": "https://i.scdn.co/image/6594334f1d1a2e65394d27eb457ccff203886411",
    },
    ]
},
...
]
```

Refactoring to use `map` was quite simple and achieved the same result. It is exactly the same line of code, but now I'm returning something inside `map` and saving it in a variable, then returning that variable to my component.

```javascript
const artistImages = getArtistData(artistData); // returns an array of strings
const roundsWithImages = rounds.map((round, index) => { 
   round.artists[currentRound].image = artistImages[index];
   return round;
});

return roundsWithImages;
```

And now hopefully my code is a little more readable and the likelihood of me messing up due to mutated variables is a little smaller!

Thank you for reading. Let me know how I can make this article better. Until next time 👋

_Cover photo by [Oliver Hale](https://unsplash.com/@4themorningshoot?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on Unsplash._