forEach and map
The for loop is universal — it can do anything. That generality is also its weakness. When you read a for loop, you have to read the whole body to understand its purpose. forEach and map communicate intent before you even read the callback.
forEach
Section titled “forEach”forEach calls a function once for every item in the array. It does not return anything — it is for side effects: logging, updating the DOM, calling another function with each item.
const expenses = [ { id: 1, description: 'Coffee', amount: 4.50, category: 'Food' }, { id: 2, description: 'Bus pass', amount: 30.00, category: 'Transport' }, { id: 3, description: 'Lunch', amount: 12.75, category: 'Food' },];
expenses.forEach(expense => { console.log(`${expense.description}: $${expense.amount}`);});// Coffee: $4.50// Bus pass: $30.00// Lunch: $12.75The callback receives three arguments: the current item, its index, and the array itself. You only need what you use:
expenses.forEach((expense, index) => { console.log(`${index + 1}. ${expense.description}`);});// 1. Coffee// 2. Bus pass// 3. LunchKey rule: forEach always returns undefined. Never assign its result to a variable expecting a transformed array — use map for that.
map calls a function once for every item and returns a new array containing the return value of each call. The original array is unchanged. Use map when you want to transform an array into a new array of the same length.
const descriptions = expenses.map(expense => expense.description);console.log(descriptions); // ['Coffee', 'Bus pass', 'Lunch']const amounts = expenses.map(expense => expense.amount);console.log(amounts); // [4.50, 30.00, 12.75]The callback receives the same three arguments as forEach (item, index, array). You return the value you want in the new array.
Transforming objects with map
Section titled “Transforming objects with map”map shines when you need to reshape objects — extract certain fields, add computed properties, or rename keys:
const summaries = expenses.map(expense => ({ label: expense.description, cost: `$${expense.amount.toFixed(2)}`,}));
console.log(summaries);// [// { label: 'Coffee', cost: '$4.50' },// { label: 'Bus pass', cost: '$30.00' },// { label: 'Lunch', cost: '$12.75' },// ]Note the parentheses around the object literal ({...}). Without them, JavaScript interprets { as the start of the function body rather than an object.
map vs forEach: the decision rule
Section titled “map vs forEach: the decision rule”Use map when… | Use forEach when… |
|---|---|
| You need a new transformed array | You need side effects only |
| The callback returns a value | The callback doesn’t return anything useful |
| You chain further methods afterward | You are done after iterating |
Never use map just to iterate — if you discard the return value, use forEach. Never use forEach when you need the transformed array — use map.
Building BudgetBuddy UI rows
Section titled “Building BudgetBuddy UI rows”In BudgetBuddy, the expense list in the DOM is built by mapping the expenses array to HTML strings, then joining them:
function renderExpenses(expenses) { const rows = expenses.map(expense => ` <li class="expense-item"> <span class="expense-desc">${expense.description}</span> <span class="expense-cat">${expense.category}</span> <span class="expense-amount">$${expense.amount.toFixed(2)}</span> </li> `);
document.querySelector('#expense-list').innerHTML = rows.join('');}One map call, one join, one DOM write. No loop, no manual string building, no index tracking.
Exercise
Section titled “Exercise”Using the full BudgetBuddy expenses array from the previous lesson:
const expenses = [ { id: 1, description: 'Coffee', amount: 4.50, category: 'Food', date: '2024-01-15' }, { id: 2, description: 'Bus pass', amount: 30.00, category: 'Transport', date: '2024-01-14' }, { id: 3, description: 'Lunch', amount: 12.75, category: 'Food', date: '2024-01-15' }, { id: 4, description: 'Gym membership', amount: 45.00, category: 'Health', date: '2024-01-10' }, { id: 5, description: 'Dinner out', amount: 38.20, category: 'Food', date: '2024-01-16' },];- Use
forEachto log each expense description to the console. - Use
mapto create an array of all expense amounts. - Use
mapto create an array of objects with just{ description, amount }— drop all other fields. - Use
mapto add aformattedAmountproperty to each expense (e.g.,'$4.50') — keep all other fields.
Log each result to confirm it looks right.
forEachiterates for side effects — DOM updates, logging, calling functions. It returnsundefined.maptransforms every item and returns a new array of the same length. The original is unchanged.- Use
mapwhen you need the result array. UseforEachwhen you do not. mapis the foundation of rendering lists in the DOM — map data to markup strings, join, and write once.