JavaScript BasicsFeatured
JavaScript forEach(): Complete Guide to Array Iteration
Master the JavaScript forEach() method for array iteration. Learn syntax, use cases, comparisons with other loops, and best practices with examples.
By JavaScriptDoc Team•
forEacharraysiterationloopsjavascript
JavaScript forEach(): Complete Guide to Array Iteration
The forEach()
method executes a provided function once for each array element. It's one of the most commonly used methods for iterating over arrays in JavaScript.
Understanding forEach()
// Basic syntax
array.forEach(function (element, index, array) {
// Code to execute for each element
});
// Arrow function syntax
array.forEach((element, index, array) => {
// Code to execute for each element
});
Basic Examples
// Simple iteration
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
console.log(num);
});
// Output: 1, 2, 3, 4, 5
// Using all parameters
const fruits = ['apple', 'banana', 'orange'];
fruits.forEach((fruit, index, array) => {
console.log(`${index}: ${fruit} from array of length ${array.length}`);
});
// 0: apple from array of length 3
// 1: banana from array of length 3
// 2: orange from array of length 3
Common Use Cases
DOM Manipulation
// Update multiple elements
const buttons = document.querySelectorAll('button');
buttons.forEach((button) => {
button.addEventListener('click', () => {
button.classList.toggle('active');
});
});
// Process form inputs
const inputs = document.querySelectorAll('input[type="text"]');
inputs.forEach((input) => {
input.value = input.value.trim();
});
Data Processing
// Calculate totals
const prices = [29.99, 45.5, 12.0, 78.25];
let total = 0;
prices.forEach((price) => {
total += price;
});
console.log(`Total: $${total.toFixed(2)}`); // Total: $165.74
// Update object properties
const users = [
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 },
{ name: 'Bob', age: 35 },
];
users.forEach((user) => {
user.isAdult = user.age >= 18;
user.ageGroup = user.age < 30 ? 'young' : 'adult';
});
forEach() vs Other Iteration Methods
forEach() vs map()
const numbers = [1, 2, 3, 4, 5];
// forEach - no return value, used for side effects
const squared1 = [];
numbers.forEach((num) => {
squared1.push(num ** 2);
});
// map - returns new array, used for transformation
const squared2 = numbers.map((num) => num ** 2);
console.log(squared1); // [1, 4, 9, 16, 25]
console.log(squared2); // [1, 4, 9, 16, 25]
forEach() vs for Loop
const items = ['a', 'b', 'c', 'd'];
// Traditional for loop - can break/continue
for (let i = 0; i < items.length; i++) {
if (items[i] === 'c') break;
console.log(items[i]);
}
// Output: a, b
// forEach - cannot break
items.forEach((item) => {
if (item === 'c') return; // Only skips current iteration
console.log(item);
});
// Output: a, b, d
forEach() vs for...of
const colors = ['red', 'green', 'blue'];
// for...of - can break/continue, works with any iterable
for (const color of colors) {
if (color === 'green') continue;
console.log(color);
}
// forEach - array method only
colors.forEach((color) => {
if (color === 'green') return;
console.log(color);
});
Working with Objects
// Iterating over object values
const person = {
name: 'John',
age: 30,
city: 'New York',
};
Object.keys(person).forEach((key) => {
console.log(`${key}: ${person[key]}`);
});
Object.values(person).forEach((value) => {
console.log(value);
});
Object.entries(person).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
Async Operations in forEach
// Problem: forEach doesn't wait for async operations
const urls = ['url1', 'url2', 'url3'];
// This doesn't work as expected
urls.forEach(async (url) => {
const response = await fetch(url);
console.log(response);
});
console.log('Done'); // Logs before fetches complete
// Solution 1: Use for...of
async function fetchAll() {
for (const url of urls) {
const response = await fetch(url);
console.log(response);
}
console.log('Done');
}
// Solution 2: Use Promise.all with map
async function fetchAllParallel() {
await Promise.all(urls.map((url) => fetch(url)));
console.log('Done');
}
Modifying Arrays During Iteration
// Adding elements
const numbers = [1, 2, 3];
numbers.forEach((num, index) => {
if (num === 2) {
numbers.push(4); // New element won't be visited
}
console.log(num);
});
// Output: 1, 2, 3
// Removing elements (not recommended)
const items = [1, 2, 3, 4, 5];
items.forEach((item, index) => {
if (item === 3) {
items.splice(index, 1); // Can cause skipping
}
});
console.log(items); // [1, 2, 4, 5]
Practical Examples
Form Validation
function validateForm(formElement) {
const errors = [];
const inputs = formElement.querySelectorAll('input[required]');
inputs.forEach((input) => {
if (!input.value.trim()) {
errors.push({
field: input.name,
message: `${input.name} is required`,
});
input.classList.add('error');
} else {
input.classList.remove('error');
}
});
return errors;
}
Shopping Cart
class ShoppingCart {
constructor() {
this.items = [];
}
addItem(item) {
this.items.push(item);
}
calculateTotal() {
let total = 0;
this.items.forEach((item) => {
total += item.price * item.quantity;
});
return total;
}
applyDiscount(percent) {
this.items.forEach((item) => {
item.price *= 1 - percent / 100;
});
}
displayItems() {
console.log('Shopping Cart:');
this.items.forEach((item, index) => {
console.log(
`${index + 1}. ${item.name} - $${item.price} x ${item.quantity}`
);
});
}
}
Data Transformation
// Process API response
const apiResponse = [
{ id: 1, first_name: 'John', last_name: 'Doe', active: 1 },
{ id: 2, first_name: 'Jane', last_name: 'Smith', active: 0 },
];
const users = [];
apiResponse.forEach((userData) => {
users.push({
id: userData.id,
fullName: `${userData.first_name} ${userData.last_name}`,
isActive: Boolean(userData.active),
});
});
Performance Considerations
// Performance comparison
const largeArray = Array(1000000).fill(1);
// forEach
console.time('forEach');
let sum1 = 0;
largeArray.forEach((num) => {
sum1 += num;
});
console.timeEnd('forEach');
// for loop (typically faster)
console.time('for');
let sum2 = 0;
for (let i = 0; i < largeArray.length; i++) {
sum2 += largeArray[i];
}
console.timeEnd('for');
// for...of
console.time('for...of');
let sum3 = 0;
for (const num of largeArray) {
sum3 += num;
}
console.timeEnd('for...of');
Common Pitfalls
Return Value
// forEach always returns undefined
const numbers = [1, 2, 3];
const result = numbers.forEach((num) => num * 2);
console.log(result); // undefined
// Use map for transformation
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6]
Breaking Out
// Cannot use break or continue
const numbers = [1, 2, 3, 4, 5];
// This doesn't work
// numbers.forEach(num => {
// if (num === 3) break; // SyntaxError
// });
// Alternatives
// 1. Use for loop or for...of
for (const num of numbers) {
if (num === 3) break;
console.log(num);
}
// 2. Use some() or every()
numbers.some((num) => {
if (num === 3) return true; // Breaks
console.log(num);
});
// 3. Throw exception (not recommended)
try {
numbers.forEach((num) => {
if (num === 3) throw new Error('Break');
console.log(num);
});
} catch (e) {
// Stopped
}
this Context
// Arrow functions
const obj = {
multiplier: 2,
numbers: [1, 2, 3],
// Works with arrow function
multiplyAll() {
this.numbers.forEach((num) => {
console.log(num * this.multiplier);
});
},
};
// Traditional function requires binding
const obj2 = {
multiplier: 2,
numbers: [1, 2, 3],
multiplyAll() {
this.numbers.forEach(function (num) {
console.log(num * this.multiplier); // undefined
});
},
};
// Solutions for traditional functions
// 1. Bind this
this.numbers.forEach(
function (num) {
console.log(num * this.multiplier);
}.bind(this)
);
// 2. Store this
const self = this;
this.numbers.forEach(function (num) {
console.log(num * self.multiplier);
});
// 3. Pass thisArg
this.numbers.forEach(function (num) {
console.log(num * this.multiplier);
}, this);
Best Practices
1. Use forEach for Side Effects
// Good use cases
const logs = [];
data.forEach((item) => {
logs.push(`Processed: ${item.id}`);
updateDatabase(item);
sendNotification(item);
});
2. Prefer map() for Transformation
// Not ideal
const squared = [];
numbers.forEach((n) => squared.push(n ** 2));
// Better
const squared = numbers.map((n) => n ** 2);
3. Consider for...of for Breakable Loops
// When you need to break
for (const item of items) {
if (shouldStop(item)) break;
process(item);
}
4. Handle Empty Arrays
const items = [];
items.forEach((item) => {
console.log(item); // Never executes
});
// No error, just does nothing
Conclusion
The forEach()
method is perfect for executing side effects on array elements. Key points:
- Executes a function for each array element
- Cannot break out of the loop
- Always returns
undefined
- Great for DOM manipulation and side effects
- Use
map()
for transformations - Use
for...of
when you need to break
Choose forEach()
when you need to perform actions on each element without creating a new array or breaking early!