JavaScript Showdown: .forEach vs. .map – Unraveling the Key Differences

Ugochukwu Gospel
7 min readSep 24, 2023

--

From watchmojo.com

Introduction:

JavaScript, the versatile language that powers the web, offers developers an array of tools to manipulate data and iterate through arrays. Two of the most commonly used methods, `.forEach` and `.map`, might seem similar at first glance, but beneath the surface, they have distinct purposes and behaviors.

When I was starting as a NodeJs backend developer, I watched tutorials online where the tutor used these two methods a lot when working with arrays, so much so that I started asking myself the difference between them and when to use each one. This is what I’ll explain in detail in this article so that even beginners would understand.

So now let’s go on a journey through the JavaScript jungle as we explore the exciting differences between these two powerful array methods :).

Here are the points we’ll be focusing on:

1. The purpose with examples

2. Return values with examples

3. Use cases with examples

4. Immutability

5. Method chaining with examples

1. The Purpose:

`.forEach`: This method is like the trusty tour guide of JavaScript. It takes you through each item in an array and allows you to perform actions on each element without changing the original array. It’s like a friendly stroll through a shop’s catalog where you can admire the things listed on them without altering them.

As an example, let’s write code to admire a shop’s drinks catalog:

const drinksCatalog = [
{ drink: ‘Coffee’, price: 3.50 },
{ drink: ‘Tea’, price: 2.99 },
{ drink: ‘Soda’, price: 3.75 },
{ drink: ‘Lemonade’, price: 5.99 },
{ drink: ‘Smoothie’, price: 2.85 }
];

drinksCatalog.forEach(el => {
if (el.price < 3) {
console.log(`So cheap?! Are you sure this is a ${el.drink}?\n`)
}
else if (el.price < 4) {
console.log(`Hmm… This one’s o…k? But I don’t take cheap ${el.drink}s…sigh\n`)
}
else {
console.log(`How can a ${el.drink} be soo expensive??\n`)
}
})

Expected output:

Hmm… This one’s o…k? But I don’t take cheap Coffees…sigh

So cheap?! Are you sure this is a Tea?

Hmm… This one’s o…k? But I don’t take cheap Sodas…sigh

How can a Lemonade be soo expensive??

So cheap?! Are you sure this is a Smoothie?

`.map`: Think of `.map` as the shop’s catalog from which you can create a brand new catalog by applying a function to each element of the original one. It’s like wanting to purchase atleast one of everything in a shop, so you get the shop’s catalog and then create a new one where you’ve specified the quantity of each item you want to purchase.

Let’s actually write the code for that:

// This is a function that generates a random integer between 0 and 10.
// I’ll use it to generate random values for the quantity field.
const randInt = () => {
return Math.floor(Math.random() * 10)
}

const drinksCatalog = [
{ drink: ‘Coffee’, price: 3.50 },
{ drink: ‘Tea’, price: 2.99 },
{ drink: ‘Soda’, price: 3.75 },
{ drink: ‘Lemonade’, price: 5.99 },
{ drink: ‘Smoothie’, price: 2.85 }
];

const orderCatalog = drinksCatalog.map(el => {
const item = el;
item.quantity = randInt()
return item
})
console.log(orderCatalog);

Expected output:

[
{ drink: ‘Coffee’, price: 3.50, quantity: 3 },
{ drink: ‘Tea’, price: 2.99, quantity: 5 },
{ drink: ‘Soda’, price: 3.75, quantity: 2 },
{ drink: ‘Lemonade’, price: 5.99, quantity: 4 },
{ drink: ‘Smoothie’, price: 2.85, quantity: 1 }
]

2. Return Values:
`.forEach`: It returns `undefined`. That’s right, it’s all about side effects – performing actions rather than producing results directly. That’s why we did not store it in a variable. Let’s actually do it and then see the output.

const drinksCatalog = [
{ drink: ‘Coffee’, price: 3.50, quantity: 3 },
{ drink: ‘Tea’, price: 2.99, quantity: 5 },
{ drink: ‘Soda’, price: 3.75, quantity: 2 },
{ drink: ‘Lemonade’, price: 5.99, quantity: 4 },
{ drink: ‘Smoothie’, price: 2.85, quantity: 1 }
]

const admireCatalog = drinksCatalog.forEach(el => {
if (el.price < 3) {
console.log(`So cheap?! Are you sure this is a ${el.drink}\n`)
}
else if (el.price < 4) {
console.log(`Hmm… This one’s o…k? But I don’t take cheap ${el.drink}s…sigh\n`)
}
else {
console.log(`How can a ${el.drink} be soo expensive??\n`)
}
})
console.log(admireCatalog)

Expected output:

undefined

`.map`: This method is the producer. It returns a new array filled with the results of applying the provided function to each element of the original array. Take the code for `.map` in section 1 for example, we were able to store the result of the `.map` operation in a variable (orderCatalog) and then log that variable to the console which outputs the new array. This is possible because the variable holds the return value of the `.map` operation which as we can see, is an array.

[
{ drink: ‘Coffee’, price: 3.50, quantity: 3 },
{ drink: ‘Tea’, price: 2.99, quantity: 5 },
{ drink: ‘Soda’, price: 3.75, quantity: 2 },
{ drink: ‘Lemonade’, price: 5.99, quantity: 4 },
{ drink: ‘Smoothie’, price: 2.85, quantity: 1 }
]

3. Use Cases:
`.forEach`: Perfect for scenarios where you need to loop through an array and perform an action on each element, like logging data to the console for example or updating the DOM.

Infact, apart from logging stuff to the console, we can also use `.forEach` to create a new array (*would explain in a second) that may or may not be of the same length as the original one. For example, imagine we want to extract all the even numbers from one array into a new array, the code can look like this

// This numbersArray contains ten numbers with four of them (6, 8, 12 and 10) being even.
//Our goal is to extract these four numbers.

const numbersArray = [6, 15, 8, 21, 12, 19, 10, 27, 17, 33];

let evenArray = [];

numbersArray.forEach(el => {
if (el % 2 === 0) evenArray.push(el)
})

console.log(evenArray)

Expected output:

[6, 8, 12, 10]

As you can see, the length of the original numbersArray is 10 while that of the new evenArray is 4. This is not possible with `.map` as the new array must be of the same length with the original one. It can even go as far as returning undefined to elements that don’t have a value. For example

const numbersArray = [6, 15, 8, 21, 12, 19, 10, 27, 17, 33];

const evenArray = numbersArray.map(el => {
If (el % 2 === 0) return el
})

console.log(evenArray)

Expected output:

[6, undefined, 8, undefined, 12, undefined, 10, undefined, undefined, undefined]

See? The length of the array remained unchanged and the `.map` operation returned undefined for numbers that are not even.

*PLEASE NOTE: While `.forEach` doesn’t return a new array, we can always declare a separate variable containing an empty array and then instead of logging to the console, we can conditionally push items into the empty array which is what we did in the example above.

`.map`: Ideal when you want to transform an array into something new, like doubling each number in an array or converting a list of names into uppercase.

As an example, let’s write code to increment our employees salaries by $10,000

const employeeSalaries = [
[“John”, 50000],
[“Alice”, 60000],
[“Bob”, 55000],
[“Eva”, 62000],
];

const newEmployeeSalaries = employeeSalaries.map(el => {
const employee = el
employee[1] += 10000
return employee
})

console.log(newEmployeeSalaries)

Expected output:

[
[“John”, 60000],
[“Alice”, 70000],
[“Bob”, 65000],
[“Eva”, 72000],
];

4. Immutability:
`.forEach`: It doesn’t create a new array, so the original one remains unchanged. That’s also why it returns undefined

`.map`: This method is all about immutability. It preserves the original array and creates a fresh one with the transformed data. Just like the `.map` part in section 1 above, it is that new array that we stored in the orderCatalog variable.

5. Chaining:
`.forEach`: You can’t chain additional array methods after a `.forEach` loop, as it doesn’t return an array, so trying to attach an array method to it would result in an error.

`.map`: Being the team player it is, `.map` returns a new array, making it chainable with other array methods, just like how a shop attendant can perform further actions on that new catalog you created in section 1, like calculating the total price of each item based on the quantity you ordered.

To do that in code, let’s attach another .map method to the order catalog and then calculate the price of each order.

const drinksCatalog = [
{ drink: ‘Coffee’, price: 3.50 },
{ drink: ‘Tea’, price: 2.99 },
{ drink: ‘Soda’, price: 3.75 },
{ drink: ‘Lemonade’, price: 5.99 },
{ drink: ‘Smoothie’, price: 2.85 }
];

const orderCatalog = drinksCatalog.map(el => {
const item = el;
item.quantity = randInt();
return item;
})

const orderPriceDetail = orderCatalog.map(el => {
const order = el;
order.orderPrice = order.price * order.quantity;
return order;
})

console.log(orderPriceDetail)

Expected output:

[
{ drink: ‘Coffee’, price: 3.50, quantity: 3, orderPrice: 10.50 },
{ drink: ‘Tea’, price: 2.99, quantity: 5, orderPrice: 14.95 },
{ drink: ‘Soda’, price: 3.75, quantity: 2, orderPrice: 7.50 },
{ drink: ‘Lemonade’, price: 5.99, quantity: 4, orderPrice: 23.96 },
{ drink: ‘Smoothie’, price: 2.85, quantity: 1, orderPrice: 2.85 }
]

Final thoughts…:
In the grand JavaScript arena, `.forEach` and `.map` are both valuable players, each with its own distinct role. `.forEach` is your trusted guide for touring and admiring adventures, while `.map` is the creative artist who crafts entirely new arrays. Understanding their differences empowers you to wield them effectively in your coding endeavors, making you a JavaScript maestro in your own right.

So, whether you’re touring a shop’s catalog just for the fun of it or buying out the entire shop, remember that in the world of JavaScript, `.forEach` and `.map` are your reliable companions, each with its own unique charm.

Happy coding 😊!

--

--

Ugochukwu Gospel

Mobile app developer (flutter) || Senior backend developer (NodeJs, Express and MongoDb)