Skip to content

map() vs forEach(): When should you use each in JavaScript?

I was confused about map() vs forEach() for months. I kept seeing code that used map() for side effects and forEach() when transformation was needed. It worked, but something felt wrong. Then I dug deeper into the functional programming principles behind these methods.

The Problem

I tried to understand map() vs forEach() from documentation, but it all sounded the same. Both “iterate over array elements” and “execute a function for each element.” But that’s like saying a hammer and a screwdriver both “hit things” - completely missing their intended purposes.

The real problem isn’t what these methods do, but what they’re designed to do. Using them incorrectly leads to bugs, unreadable code, and violates functional programming principles.

The Direct Answer

Use map() when you need to transform array elements into a new array with different values, returning a new collection. Use forEach() when you need to perform side effects (like logging, DOM updates, or API calls) without creating a new array. Never use map() for side effects - that’s what forEach() is designed for.

The Solution

map() - Data Transformation

Correct usage of map() for data transformation
// CORRECT: Use map() for transformation
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
const users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"}
];
const userNames = users.map(u => u.name); // ["John", "Pete"]

map() returns a new array. That’s its entire purpose. Each element goes in, gets transformed, comes out in a new array. The original array stays unchanged.

forEach() - Side Effects

Correct usage of forEach() for side effects
// CORRECT: Use forEach() for side effects
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
button.addEventListener('click', handleClick);
});
numbers.forEach(n => {
console.log(`Number: ${n}`);
API.logToDatabase(n); // Side effect
});

forEach() returns undefined. It’s designed for when you need to do something with each element but don’t need a new array. Side effects like logging, DOM manipulation, API calls - that’s forEach()‘s sweet spot.

Why This Matters

I tried using map() for side effects once. It worked, but then I had to remember that the returned array was meaningless and should be ignored. It created cognitive load and confusion for anyone reading the code.

When you use the right method:

  1. Code is self-documenting - map() clearly says “I’m transforming data”
  2. Functional purity - map() has no side effects, making code easier to reason about
  3. Performance - forEach() can be more efficient when you don’t need a new array
  4. No surprises - forEach() returns undefined, so no accidental array creation

Common Mistakes I’ve Seen

Using map() for side effects

Incorrect usage of map() for side effects
// INCORRECT: Using map() for side effects
const badResult = numbers.map(n => {
console.log(`Processing ${n}`); // Side effect
return n * 2;
});

This works technically, but it’s wrong. You’re creating an array you don’t need, and anyone reading this expects a transformed array, not logging side effects.

Using forEach() when transformation is needed

Incorrect usage of forEach() for transformation
// INCORRECT: Using forEach() when transformation is needed
const badTransform = numbers.forEach(n => n * 2); // Returns undefined!

I’ve seen this mistake countless times. The developer wants a new array with transformed values but uses forEach(), which returns undefined. The result is often bugs where undefined gets used later.

The Hybrid Approach

Incorrect manual array creation with forEach()
// REALLY WRONG: Using forEach() and creating array manually
const manualTransform = [];
numbers.forEach(n => {
manualTransform.push(n * 2); // This is what map() does for you!
});

This is the worst of both worlds. You’re doing exactly what map() does, but manually. You lose the declarative nature and introduce the risk of bugs.

When to Use Each

Use map() when:

  • You need a new array with transformed values
  • You’re doing pure data transformation
  • You want to chain array methods (map().filter().reduce())
  • You need to preserve the original array

Use forEach() when:

  • You need side effects (logging, DOM updates, API calls)
  • You’re modifying external state
  • You don’t need a return value
  • You’re working with async operations that don’t need array chaining

The Functional Programming Principle

From the JavaScript community consensus: map() should only transform data, not cause side effects.

When I understood this principle, everything clicked. It’s not about what the methods can technically do, but what they should do. This is the core of functional programming - pure functions that transform data without side effects.

Conclusion

Choose map() when you need to create a new array from existing data, and forEach() when you need to perform actions on each element without creating a new array. Follow the functional programming principle: map() transforms data, forEach() causes side effects.

Once you understand this distinction, your code becomes more readable, maintainable, and follows the intended patterns of JavaScript array methods.

References

  • [Understanding filter() vs reduce() in JavaScript]
  • [JavaScript Array Methods: When to use which one]
  • [Functional Programming Principles for JavaScript Developers]

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments