Array iteration methods are powerful tools that make working with arrays more elegant and functional. Instead of writing traditional for loops, you can use methods like forEach, map, and filter to process arrays in a more declarative way. These methods are fundamental to modern JavaScript and are used extensively in real-world applications. Let's master these essential iteration patterns!
Why Use Iteration Methods?
Cleaner and more declarative
Traditional Loop
// Traditional for loop
let numbers = [1, 2, 3, 4, 5];
let doubled = [];
for (let i = 0; i < numbers.length; i++) {
doubled.push(numbers[i] * 2);
}
console.log(doubled); // [2, 4, 6, 8, 10]
// More code, manual index management
// Easy to make off-by-one errorsModern Iteration Method
// Modern map method
let numbers = [1, 2, 3, 4, 5];
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// Cleaner, more readable
// No index management needed
// Intent is clearBenefits of iteration methods:
- More readable and declarative
- Less code to write
- No manual index management
- Functional programming style
- Chainable for complex operations
- Harder to make mistakes
forEach() - Execute for Each Element
The forEach() method executes a provided function once for each array element. It's used for side effects, not transformations.
Basic Syntax
// array.forEach(callback(element, index, array))
// element: current element being processed
// index: index of current element (optional)
// array: the array forEach was called on (optional)
let fruits = ["apple", "banana", "orange"];
fruits.forEach(function(fruit) {
console.log(fruit);
});
// Output:
// apple
// banana
// orange
// With arrow function (cleaner)
fruits.forEach(fruit => console.log(fruit));Using All Parameters
let colors = ["red", "green", "blue"];
colors.forEach((color, index, array) => {
console.log(`Index ${index}: ${color}`);
console.log(`Array length: ${array.length}`);
});
// Output:
// Index 0: red
// Array length: 3
// Index 1: green
// Array length: 3
// Index 2: blue
// Array length: 3Common Use Cases
// 1. Logging/Debugging
let numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => console.log(`Number: ${num}`));
// 2. Accumulating values
let sum = 0;
numbers.forEach(num => {
sum += num;
});
console.log("Sum:", sum); // 15
// 3. Modifying external data
let doubled = [];
numbers.forEach(num => {
doubled.push(num * 2);
});
console.log(doubled); // [2, 4, 6, 8, 10]
// 4. Calling functions
function processItem(item) {
console.log(`Processing ${item}`);
}
let tasks = ["task1", "task2", "task3"];
tasks.forEach(processItem);
// 5. Object property access
let users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 }
];
users.forEach(user => {
console.log(`${user.name} is ${user.age} years old`);
});Important Characteristics
let arr = [1, 2, 3];
// forEach returns undefined (not a new array)
let result = arr.forEach(num => num * 2);
console.log(result); // undefined
// Cannot break or continue
arr.forEach(num => {
if (num === 2) {
// break; // Syntax Error!
// continue; // Syntax Error!
return; // Only exits current iteration, not loop
}
console.log(num);
});
// Output: 1, 3 (skips 2 but continues)
// Does not modify original array
let numbers = [1, 2, 3];
numbers.forEach(num => num * 2);
console.log(numbers); // [1, 2, 3] (unchanged)Important: forEach() always returns undefined. If you need to create a new array, use map() instead. You cannot break out of a forEach loop.
map() - Transform Each Element
The map() method creates a NEW array with the results of calling a function on every element. It's perfect for transforming data.
Basic Syntax
// array.map(callback(element, index, array))
// Returns: new array with transformed elements
let numbers = [1, 2, 3, 4, 5];
// Double each number
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (original unchanged)
// Square each number
let squared = numbers.map(num => num ** 2);
console.log(squared); // [1, 4, 9, 16, 25]Transforming Different Data Types
// Numbers to strings
let numbers = [1, 2, 3];
let strings = numbers.map(num => `Number ${num}`);
console.log(strings); // ["Number 1", "Number 2", "Number 3"]
// Strings to uppercase
let fruits = ["apple", "banana", "orange"];
let uppercased = fruits.map(fruit => fruit.toUpperCase());
console.log(uppercased); // ["APPLE", "BANANA", "ORANGE"]
// Strings to lengths
let words = ["hi", "hello", "hey"];
let lengths = words.map(word => word.length);
console.log(lengths); // [2, 5, 3]
// Extract property from objects
let users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 }
];
let names = users.map(user => user.name);
console.log(names); // ["Alice", "Bob", "Charlie"]
let ages = users.map(user => user.age);
console.log(ages); // [25, 30, 35]Creating New Objects
let products = [
{ name: "Laptop", price: 1000 },
{ name: "Mouse", price: 25 },
{ name: "Keyboard", price: 75 }
];
// Add tax to each product
let withTax = products.map(product => ({
name: product.name,
price: product.price,
priceWithTax: (product.price * 1.08).toFixed(2)
}));
console.log(withTax);
// [
// { name: "Laptop", price: 1000, priceWithTax: "1080.00" },
// { name: "Mouse", price: 25, priceWithTax: "27.00" },
// { name: "Keyboard", price: 75, priceWithTax: "81.00" }
// ]
// Transform user data
let rawUsers = [
{ firstName: "Alice", lastName: "Smith", age: 25 },
{ firstName: "Bob", lastName: "Jones", age: 30 }
];
let formattedUsers = rawUsers.map(user => ({
fullName: `${user.firstName} ${user.lastName}`,
isAdult: user.age >= 18
}));
console.log(formattedUsers);
// [
// { fullName: "Alice Smith", isAdult: true },
// { fullName: "Bob Jones", isAdult: true }
// ]Using Index Parameter
let letters = ["a", "b", "c"];
// Add index to each element
let indexed = letters.map((letter, index) => ({
index: index,
letter: letter,
position: index + 1
}));
console.log(indexed);
// [
// { index: 0, letter: "a", position: 1 },
// { index: 1, letter: "b", position: 2 },
// { index: 2, letter: "c", position: 3 }
// ]
// Create numbered list
let items = ["milk", "bread", "eggs"];
let numbered = items.map((item, i) => `${i + 1}. ${item}`);
console.log(numbered);
// ["1. milk", "2. bread", "3. eggs"]Complex Transformations
let students = [
{ name: "Alice", scores: [85, 92, 78] },
{ name: "Bob", scores: [90, 88, 95] },
{ name: "Charlie", scores: [78, 85, 80] }
];
// Calculate average for each student
let withAverages = students.map(student => {
let sum = student.scores.reduce((a, b) => a + b, 0);
let average = sum / student.scores.length;
return {
name: student.name,
average: average.toFixed(2),
grade: average >= 90 ? "A" :
average >= 80 ? "B" :
average >= 70 ? "C" : "F"
};
});
console.log(withAverages);
// [
// { name: "Alice", average: "85.00", grade: "B" },
// { name: "Bob", average: "91.00", grade: "A" },
// { name: "Charlie", average: "81.00", grade: "B" }
// ]Best Practice: Use map() when you need to transform every element and create a new array. Always return a value from the callback function.
filter() - Select Elements
The filter() method creates a NEW array with all elements that pass a test. It's perfect for selecting subsets of data.
Basic Syntax
// array.filter(callback(element, index, array))
// Returns: new array with elements that pass test (return true)
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Get even numbers
let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]
// Get numbers greater than 5
let large = numbers.filter(num => num > 5);
console.log(large); // [6, 7, 8, 9, 10]
// Get numbers in range
let inRange = numbers.filter(num => num >= 3 && num <= 7);
console.log(inRange); // [3, 4, 5, 6, 7]Filtering Objects
let users = [
{ name: "Alice", age: 25, active: true },
{ name: "Bob", age: 17, active: true },
{ name: "Charlie", age: 30, active: false },
{ name: "Diana", age: 22, active: true }
];
// Get active users
let activeUsers = users.filter(user => user.active);
console.log(activeUsers);
// [
// { name: "Alice", age: 25, active: true },
// { name: "Bob", age: 17, active: true },
// { name: "Diana", age: 22, active: true }
// ]
// Get adult users (18+)
let adults = users.filter(user => user.age >= 18);
console.log(adults);
// [
// { name: "Alice", age: 25, active: true },
// { name: "Charlie", age: 30, active: false },
// { name: "Diana", age: 22, active: true }
// ]
// Multiple conditions
let activeAdults = users.filter(user => {
return user.active && user.age >= 18;
});
console.log(activeAdults);
// [
// { name: "Alice", age: 25, active: true },
// { name: "Diana", age: 22, active: true }
// ]Common Filter Patterns
let products = [
{ name: "Laptop", price: 1000, inStock: true },
{ name: "Mouse", price: 25, inStock: true },
{ name: "Monitor", price: 300, inStock: false },
{ name: "Keyboard", price: 75, inStock: true },
{ name: "Webcam", price: 150, inStock: false }
];
// Filter by availability
let available = products.filter(p => p.inStock);
console.log(`${available.length} products available`);
// Filter by price range
let affordable = products.filter(p => p.price < 100);
console.log(affordable);
// [{ name: "Mouse", ... }, { name: "Keyboard", ... }]
// Multiple conditions
let affordableInStock = products.filter(p => {
return p.inStock && p.price < 500;
});
console.log(affordableInStock);
// Filter strings
let words = ["apple", "banana", "apricot", "cherry", "avocado"];
// Words starting with 'a'
let startsWithA = words.filter(word => word.startsWith("a"));
console.log(startsWithA); // ["apple", "apricot", "avocado"]
// Words longer than 5 characters
let longWords = words.filter(word => word.length > 5);
console.log(longWords); // ["banana", "apricot", "avocado"]Filtering with Index
let numbers = [10, 20, 30, 40, 50, 60];
// Get elements at even indices
let evenIndices = numbers.filter((num, index) => index % 2 === 0);
console.log(evenIndices); // [10, 30, 50]
// Get elements at odd indices
let oddIndices = numbers.filter((num, index) => index % 2 !== 0);
console.log(oddIndices); // [20, 40, 60]
// Skip first element
let withoutFirst = numbers.filter((num, index) => index > 0);
console.log(withoutFirst); // [20, 30, 40, 50, 60]Removing Falsy Values
let mixed = [0, 1, false, 2, "", 3, null, undefined, 4, NaN];
// Remove all falsy values
let truthyOnly = mixed.filter(value => value);
console.log(truthyOnly); // [1, 2, 3, 4]
// Or use Boolean as filter
let truthyOnly2 = mixed.filter(Boolean);
console.log(truthyOnly2); // [1, 2, 3, 4]
// Remove null and undefined only
let noNullish = mixed.filter(value => value !== null && value !== undefined);
console.log(noNullish); // [0, 1, false, 2, "", 3, 4, NaN]Removing Duplicates
let numbers = [1, 2, 2, 3, 3, 3, 4, 4, 5];
// Remove duplicates using filter + indexOf
let unique = numbers.filter((num, index, array) => {
return array.indexOf(num) === index;
});
console.log(unique); // [1, 2, 3, 4, 5]
// How it works:
// For each element, check if its first occurrence
// (indexOf) is at the current index
// If yes, keep it; if no, it's a duplicate
// Modern way (using Set)
let unique2 = [...new Set(numbers)];
console.log(unique2); // [1, 2, 3, 4, 5]Chaining Methods
You can chain multiple array methods together to perform complex operations elegantly.
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Filter then map
let result = numbers
.filter(num => num % 2 === 0) // Get evens: [2, 4, 6, 8, 10]
.map(num => num ** 2); // Square them: [4, 16, 36, 64, 100]
console.log(result); // [4, 16, 36, 64, 100]
// More complex chain
let users = [
{ name: "Alice", age: 25, city: "NYC" },
{ name: "Bob", age: 17, city: "LA" },
{ name: "Charlie", age: 30, city: "NYC" },
{ name: "Diana", age: 22, city: "Chicago" }
];
let nycAdultNames = users
.filter(user => user.city === "NYC") // NYC users only
.filter(user => user.age >= 18) // Adults only
.map(user => user.name) // Get names
.map(name => name.toUpperCase()); // Uppercase
console.log(nycAdultNames); // ["ALICE", "CHARLIE"]
// Practical example: Product processing
let products = [
{ name: "Laptop", price: 1000, category: "Electronics", inStock: true },
{ name: "Mouse", price: 25, category: "Electronics", inStock: true },
{ name: "Shirt", price: 30, category: "Clothing", inStock: false },
{ name: "Phone", price: 800, category: "Electronics", inStock: true }
];
let electronicsForSale = products
.filter(p => p.category === "Electronics") // Electronics only
.filter(p => p.inStock) // In stock only
.map(p => ({
name: p.name,
discountPrice: (p.price * 0.9).toFixed(2) // 10% off
}));
console.log(electronicsForSale);
// [
// { name: "Laptop", discountPrice: "900.00" },
// { name: "Mouse", discountPrice: "22.50" },
// { name: "Phone", discountPrice: "720.00" }
// ]forEach vs map vs filter
| Method | Purpose | Returns | Use When |
|---|---|---|---|
forEach | Execute action | undefined | Side effects, no new array needed |
map | Transform | New array (same length) | Need transformed version |
filter | Select | New array (subset) | Need subset that passes test |
let numbers = [1, 2, 3, 4, 5];
// forEach - just execute
numbers.forEach(num => console.log(num));
// Output: 1, 2, 3, 4, 5
// Returns: undefined
// map - transform all
let doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// Returns: new array with same length
// filter - select some
let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]
// Returns: new array with subsetPractical Examples
Example 1: E-commerce Product Filter
let products = [
{ id: 1, name: "Laptop", price: 1200, category: "Electronics", rating: 4.5 },
{ id: 2, name: "Mouse", price: 25, category: "Electronics", rating: 4.2 },
{ id: 3, name: "Shirt", price: 30, category: "Clothing", rating: 3.8 },
{ id: 4, name: "Phone", price: 800, category: "Electronics", rating: 4.7 },
{ id: 5, name: "Pants", price: 50, category: "Clothing", rating: 4.0 }
];
function filterProducts(products, filters) {
return products
.filter(p => {
// Filter by category
if (filters.category && p.category !== filters.category) {
return false;
}
// Filter by price range
if (filters.maxPrice && p.price > filters.maxPrice) {
return false;
}
// Filter by rating
if (filters.minRating && p.rating < filters.minRating) {
return false;
}
return true;
})
.map(p => ({
id: p.id,
name: p.name,
displayPrice: `$${p.price}`,
rating: `⭐ ${p.rating}`
}));
}
// Get affordable electronics with good ratings
let results = filterProducts(products, {
category: "Electronics",
maxPrice: 900,
minRating: 4.0
});
console.log(results);
// [
// { id: 2, name: "Mouse", displayPrice: "$25", rating: "⭐ 4.2" },
// { id: 4, name: "Phone", displayPrice: "$800", rating: "⭐ 4.7" }
// ]Example 2: Student Grade Processor
let students = [
{ name: "Alice", scores: [85, 92, 78, 95] },
{ name: "Bob", scores: [70, 68, 72, 65] },
{ name: "Charlie", scores: [90, 88, 92, 95] },
{ name: "Diana", scores: [55, 60, 58, 52] }
];
function processGrades(students) {
return students
.map(student => {
// Calculate average
let sum = student.scores.reduce((a, b) => a + b, 0);
let average = sum / student.scores.length;
// Determine grade
let grade = average >= 90 ? "A" :
average >= 80 ? "B" :
average >= 70 ? "C" :
average >= 60 ? "D" : "F";
return {
name: student.name,
average: average.toFixed(2),
grade: grade,
passing: average >= 60
};
})
.filter(student => student.passing) // Only passing students
.map(student =>
`${student.name}: ${student.grade} (${student.average}%)`
);
}
let passingStudents = processGrades(students);
console.log("Passing students:");
passingStudents.forEach(student => console.log(student));
// Output:
// Alice: B (87.50%)
// Bob: C (68.75%)
// Charlie: A (91.25%)Array Iteration Methods Practice
Experiment with forEach, map, and filter
console.log() to see your output in the console above.Key Takeaways
forEach()executes a function for each element, returns undefinedmap()transforms each element, returns new array with same lengthfilter()selects elements that pass test, returns new array (subset)- Use
forEach()for side effects (logging, DOM updates) - Use
map()when you need a transformed version of the array - Use
filter()when you need a subset based on conditions - All three methods don't modify the original array
- Chain methods for complex data transformations
- Callback receives (element, index, array) parameters
- More readable and maintainable than traditional for loops
What's Next?
You now understand the three most common array iteration methods— forEach, map, and filter! These methods form the foundation of functional programming in JavaScript and are used constantly in modern applications.
In the next lesson, we'll explore Advanced Array Methods—learning find, findIndex, some, every, and reduce. These powerful methods enable sophisticated array operations and data processing!
💪 Practice Challenge:
Before moving on, try creating:
- Use map to convert an array of Celsius temperatures to Fahrenheit
- Use filter to get all users older than 25 from an array of user objects
- Chain filter and map to get uppercase names of active users
- Use forEach to calculate the total price of items in a shopping cart
- Create a data processing pipeline that filters, transforms, and formats product data