ForEach vs Map in JavaScript
January 4, 2026
ForEach vs Map in JavaScript
Understanding the difference between forEach() and map() is crucial for writing effective JavaScript code. While they appear similar, they serve different purposes and have distinct behaviors that affect how you can use them.
Key Differences
| Aspect | forEach() | map() |
| ---------------- | ----------------------------------------------- | --------------------------------------- |
| Return Value | undefined | New array |
| Mutability | Mutates original array (if you modify elements) | Creates new array (immutable approach) |
| Chainability | Cannot be chained | Can be chained with other array methods |
| Use Case | Side effects (logging, DOM manipulation) | Data transformation |
| Performance | Slightly faster (no new array creation) | Slightly slower (creates new array) |
forEach() Method
The forEach() method executes a provided function once for each element in an array. It doesn't return anything (undefined) and is primarily used for side effects.
Characteristics
- No Return Value: Always returns
undefined - Mutator Method: Can modify the original array if you mutate elements
- Not Chainable: Cannot chain with other array methods
- Side Effects: Best for operations that don't need to return values
Example
const numbers = [1, 2, 3, 4, 5];
// forEach doesn't return anything
const result = numbers.forEach((num) => {
console.log(num * 2);
});
console.log(result); // undefined
// Modifying original array (not recommended, but possible)
const arr = [1, 2, 3];
arr.forEach((item, index) => {
arr[index] = item * 2;
});
console.log(arr); // [2, 4, 6]
Common Use Cases
// 1. Logging
const users = ["Alice", "Bob", "Charlie"];
users.forEach((user) => console.log(user));
// 2. DOM Manipulation
const buttons = document.querySelectorAll("button");
buttons.forEach((button) => {
button.addEventListener("click", handleClick);
});
// 3. Side Effects
const items = [{ id: 1 }, { id: 2 }];
items.forEach((item) => {
item.processed = true; // Mutating objects in array
});
// 4. API Calls (fire and forget)
const userIds = [1, 2, 3];
userIds.forEach((id) => {
fetch(`/api/users/${id}`).then(/* ... */);
});
map() Method
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array. It's ideal for data transformation.
Characteristics
- Returns New Array: Always returns a new array
- Immutable: Doesn't modify the original array
- Chainable: Can be chained with other array methods
- Transformation: Best for creating new data structures
Example
const numbers = [1, 2, 3, 4, 5];
// map returns a new array
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (unchanged)
// Chainable
const result = numbers
.map((num) => num * 2)
.filter((num) => num > 4)
.sort((a, b) => a - b);
console.log(result); // [6, 8, 10]
Common Use Cases
// 1. Data Transformation
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
];
const names = users.map((user) => user.name);
// ["Alice", "Bob"]
// 2. Formatting Data
const prices = [10, 20, 30];
const formattedPrices = prices.map((price) => `${price.toFixed(2)}`);
// ["$10.00", "$20.00", "$30.00"]
// 3. Extracting Properties
const products = [
{ id: 1, name: "Laptop", price: 1000 },
{ id: 2, name: "Phone", price: 500 },
];
const productIds = products.map((product) => product.id);
// [1, 2]
// 4. Complex Transformations
const numbers = [1, 2, 3];
const squares = numbers.map((num) => ({
original: num,
squared: num * num,
isEven: num % 2 === 0,
}));
When to Use Each
Use forEach() when:
- ✅ You need to perform side effects (logging, DOM updates)
- ✅ You don't need the return value
- ✅ You want to modify the original array (though this is generally not recommended)
- ✅ You're iterating for the purpose of iteration only
// Good use of forEach
const errors = [];
data.forEach((item) => {
if (!item.valid) {
errors.push(item); // Side effect: collecting errors
}
});
Use map() when:
- ✅ You need to transform data into a new array
- ✅ You want to chain multiple array operations
- ✅ You want to maintain immutability
- ✅ You need the result for further processing
// Good use of map
const processedData = rawData
.map((item) => transformItem(item))
.filter((item) => item.isValid)
.sort((a, b) => a.priority - b.priority);
Common Mistakes
Mistake 1: Using forEach when you need a new array
// ❌ Wrong
const numbers = [1, 2, 3];
const doubled = [];
numbers.forEach((num) => {
doubled.push(num * 2);
});
// ✅ Correct
const doubled = numbers.map((num) => num * 2);
Mistake 2: Using map for side effects
// ❌ Wrong - map should be used for transformation
const users = ["Alice", "Bob"];
users.map((user) => console.log(user)); // Creates unnecessary array
// ✅ Correct
users.forEach((user) => console.log(user));
Mistake 3: Trying to chain after forEach
// ❌ Wrong - forEach returns undefined
const numbers = [1, 2, 3];
numbers.forEach((num) => num * 2).filter((num) => num > 2); // Error!
// ✅ Correct
const result = numbers.map((num) => num * 2).filter((num) => num > 2);
Performance Considerations
forEach() Performance
- Slightly faster for simple iterations
- No memory overhead for new array creation
- Better for large arrays when you don't need a result
map() Performance
- Slightly slower due to new array creation
- Memory overhead for the new array
- Better when you need the transformed data
// Performance test example
const largeArray = Array.from({ length: 1000000 }, (_, i) => i);
// forEach - faster for side effects
console.time("forEach");
largeArray.forEach((item) => {
// side effect operation
});
console.timeEnd("forEach");
// map - creates new array
console.time("map");
const newArray = largeArray.map((item) => item * 2);
console.timeEnd("map");
Similarities
Both methods:
- Iterate through array elements
- Execute a callback function for each element
- Provide access to
(element, index, array)in the callback - Skip empty slots in sparse arrays
- Don't execute for empty arrays
const arr = [1, 2, 3];
// Both provide same callback parameters
arr.forEach((element, index, array) => {
console.log(element, index, array);
});
arr.map((element, index, array) => {
return element * 2;
});
Summary
forEach(): Use for side effects, when you don't need a return value, and for simple iterationmap(): Use for data transformation, when you need a new array, and when you want to chain operations
Choosing the right method makes your code more readable, maintainable, and aligned with functional programming principles. Remember: if you're creating a new array, use map(). If you're just iterating for side effects, use forEach().