Back to Blog
Tutorial2025-01-09

map() vs forEach(): Which One Should You Use?

A deep dive into the differences between map() and forEach(), when to use each, and common mistakes to avoid.

The Fundamental Difference

At first glance, map() and forEach() look almost identical. Both iterate over arrays, both execute a callback function for each element. But there's a crucial difference that changes everything: map() returns a new array, forEach() returns undefined.

This seemingly small distinction has massive implications for how and when you should use each method.

``javascript const numbers = [1, 2, 3, 4, 5];

// forEach returns undefined const forEachResult = numbers.forEach(n => n * 2); console.log(forEachResult); // undefined

// map returns a new array const mapResult = numbers.map(n => n * 2); console.log(mapResult); // [2, 4, 6, 8, 10] `

When to Use map()

Use map() when you need to transform data. The name itself gives you a hint - you're "mapping" each element to a new value.

`javascript // Transform user objects to just names const users = [ { id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 30 }, { id: 3, name: 'Charlie', age: 35 } ];

const names = users.map(user => user.name); // ['Alice', 'Bob', 'Charlie']

// Convert temperatures from Celsius to Fahrenheit const celsius = [0, 20, 30, 100]; const fahrenheit = celsius.map(c => (c * 9/5) + 32); // [32, 68, 86, 212]

// Parse strings to numbers const stringNumbers = ['1', '2', '3']; const actualNumbers = stringNumbers.map(Number); // [1, 2, 3] `

Key insight: map() is pure - it doesn't modify the original array and produces predictable output for the same input. This makes your code easier to test and debug.

When to Use forEach()

Use forEach() when you need to perform side effects - actions that affect something outside the callback function.

`javascript // Logging each item users.forEach(user => { console.log(Processing user: ${user.name}); });

// Updating DOM elements const items = document.querySelectorAll('.item'); items.forEach(item => { item.classList.add('processed'); });

// Accumulating to an external variable (though reduce is better) let total = 0; prices.forEach(price => { total += price; });

// Sending analytics events purchases.forEach(purchase => { analytics.track('purchase', purchase); }); `

The Performance Myth

Many developers believe forEach() is faster because it doesn't create a new array. In reality, the performance difference is negligible for most use cases. Modern JavaScript engines optimize both methods heavily.

`javascript // Both are fast enough for typical use const largeArray = Array.from({ length: 10000 }, (_, i) => i);

console.time('map'); largeArray.map(n => n * 2); console.timeEnd('map'); // ~1-2ms

console.time('forEach'); largeArray.forEach(n => n * 2); console.timeEnd('forEach'); // ~1-2ms `

Choose based on intent, not performance. If you need the result, use map(). If you don't, use forEach().

Common Mistakes to Avoid

Mistake 1: Using map() but ignoring the result

`javascript // BAD - map() result is thrown away users.map(user => { console.log(user.name); });

// GOOD - use forEach() for side effects users.forEach(user => { console.log(user.name); }); `

This is wasteful because map() creates a new array that immediately gets garbage collected.

Mistake 2: Using forEach() when you need the result

`javascript // BAD - awkward pattern with external variable const doubled = []; numbers.forEach(n => { doubled.push(n * 2); });

// GOOD - map() is cleaner and more functional const doubled = numbers.map(n => n * 2); `

Mistake 3: Trying to break out of forEach()

`javascript // BAD - return doesn't stop forEach numbers.forEach(n => { if (n === 3) return; // This only skips current iteration! console.log(n); });

// GOOD - use for...of if you need to break for (const n of numbers) { if (n === 3) break; console.log(n); } `

Method Chaining: map()'s Superpower

Because map() returns an array, you can chain multiple operations together:

`javascript const result = users .map(user => user.name) // Get names .map(name => name.toUpperCase()) // Uppercase .filter(name => name.length > 3); // Filter short names

// forEach can't chain like this `

Real-World Example: Data Processing Pipeline

`javascript // API response processing with map() const apiResponse = [ { id: 1, first_name: 'john', last_name: 'doe', created_at: '2024-01-15' }, { id: 2, first_name: 'jane', last_name: 'smith', created_at: '2024-01-16' } ];

const processedUsers = apiResponse.map(user => ({ id: user.id, fullName: ${user.first_name} ${user.last_name}.split(' ') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '), createdAt: new Date(user.created_at) }));

// Result: // [ // { id: 1, fullName: 'John Doe', createdAt: Date object }, // { id: 2, fullName: 'Jane Smith', createdAt: Date object } // ] ``

Summary: The Decision Framework

| Scenario | Use | |----------|-----| | Need transformed array | map() | | Performing side effects | forEach() | | Method chaining | map() | | DOM manipulation | forEach() | | Data transformation | map() | | Logging/debugging | forEach() |

Remember: If you're creating a new array from an existing one, use map(). If you're "doing something" with each element without needing results, use forEach().