SKU // 69

JavaScript Array Iterations

Iteration methods run a function on every element of an array. Instead of writing a loop, a counter, and an empty result array each time, you describe what should happen to each item and the method handles the looping. The big four are forEach, map, filter, and reduce.

// First: Plain Loops

Before the methods, the loop statements. for...of (from JS Loops) hands you each value, and is the recommended loop for arrays. for...in hands you each index, as a string:

const cars = ["BMW", "Volvo", "Mini"];

for (const x of cars) console.log(x);
for (const x in cars) console.log(x, typeof x);
BMW Volvo Mini 0 string 1 string 2 string
Not recommended: for...in on arrays
It works (you can read cars[x]), but for...in was built to list an object's property names. The indexes come out as strings, so x + 1 gives "01", and any extra properties on the array show up too. Use for...of, a counting for loop, or the methods below.

// The Callback Receives Three Things

array.forEach((value, index, wholeArray) => { ... });

Most of the time you only need value, sometimes index, rarely the third.

The function you pass is called a callback: you hand it over, and the method calls it back once per element. It does not have to be an arrow. A named function works the same, and you can leave off parameters you do not use:

function double(value) {
  return value * 2;
}

console.log([45, 4, 9].map(double));   // pass it; do not call it
[90, 8, 18]

// forEach(): Do Something With Each

const names = ["Ava", "Ben", "Cal"];

names.forEach((name, i) => {
  console.log(`${i + 1}. ${name}`);
});
1. Ava 2. Ben 3. Cal
Watch out
forEach always returns undefined, and you cannot stop it early with break. If you need a result, use map or filter. If you need to stop early, use a for...of loop or find.

// map(): Transform Each Into Something New

map returns a new array of the same length, containing whatever your function returns for each element:

const prices = [10, 25, 40];

const doubled = prices.map(p => p * 2);
const labels  = prices.map(p => `$${p.toFixed(2)}`);

console.log(doubled);
console.log(labels);
[20, 50, 80] ["$10.00", "$25.00", "$40.00"]
// Pulling one property out of a list of objects
const students = [{ name: "Ava", gpa: 3.8 }, { name: "Ben", gpa: 3.1 }];
students.map(s => s.name)   // ["Ava", "Ben"]

map skips empty slots (the holes from JS Array Constructor): the hole stays a hole in the result. And when each element should become several, use flatMap, which maps and then flattens one level:

console.log(["hi there", "bye"].flatMap(s => s.split(" ")));
["hi", "there", "bye"]

// filter(): Keep Only What Passes

filter returns a new array with only the elements where your function returns true:

const scores = [72, 88, 95, 61, 99];

const passing = scores.filter(s => s >= 70);
const aGrades = scores.filter(s => s >= 90);

console.log(passing);
console.log(aGrades);
[72, 88, 95, 99] [95, 99]

// reduce(): Boil Everything Down to One Value

reduce carries a running result (the accumulator) through the array. Each call returns the updated accumulator for the next element:

const cart = [4.50, 12.00, 3.25];

const total = cart.reduce((sum, price) => sum + price, 0);
//                         accumulator  element         starting value

console.log(total);
19.75

Step by step: sum starts at 0. Then 0 + 4.50 = 4.50, then 4.50 + 12.00 = 16.50, then 16.50 + 3.25 = 19.75.

Tip
Always pass the starting value (the 0 above). Without it, reduce uses the first element as the start, and on an empty array it throws a TypeError.
// reduce can build any kind of result: here, a tally object
const votes = ["red", "blue", "red", "green", "red"];

const tally = votes.reduce((counts, v) => {
  counts[v] = (counts[v] ?? 0) + 1;
  return counts;
}, {});

console.log(tally);
{red: 3, blue: 1, green: 1}

The starting value does not have to be 0. [45, 4, 9, 16, 25].reduce((t, v) => t + v, 100) gives 199, because the running total begins at 100.

reduceRight(): The Same, Backward

reduceRight works exactly like reduce but goes from the last element to the first:

const letters = ["a", "b", "c"];

console.log(letters.reduce((s, v) => s + v, ""));
console.log(letters.reduceRight((s, v) => s + v, ""));
abc cba

// Chaining: The Real Power

Because map and filter return arrays, you can chain them into a pipeline that reads like a sentence:

const orders = [
  { item: "Lamp",  price: 24, shipped: true },
  { item: "Desk",  price: 180, shipped: false },
  { item: "Chair", price: 95, shipped: true }
];

const shippedTotal = orders
  .filter(o => o.shipped)            // keep shipped orders
  .map(o => o.price)                // take their prices
  .reduce((sum, p) => sum + p, 0);   // add them up

console.log(shippedTotal);
119

// None of These Change the Original

map, filter, and reduce all leave the original array untouched and give you a new result. That makes them safe to use without side effects.

// every() and some()

These two also run a test function on the elements, but answer with true or false: does every element pass, or do some? They are covered with examples in Array Search.

// keys() and entries()

keys() gives you the indexes, and entries() gives you [index, value] pairs. Both return an iterator: something you loop over with for...of (JS Iterators explains them fully):

const fruits = ["Banana", "Orange", "Apple"];

for (const i of fruits.keys()) console.log(i);

for (const pair of fruits.entries()) {
  console.log(pair[0], pair[1]);
}
0 1 2 0 Banana 1 Orange 2 Apple

// with(): Change One Element, Safely

arr.with(index, value) (added in 2023) returns a copy with one element replaced. The original is untouched, like toSorted and toSpliced:

const months = ["Jan", "Feb", "Mar"];
const fixed = months.with(2, "March");

console.log(fixed);
console.log(months);
["Jan", "Feb", "March"] ["Jan", "Feb", "Mar"]

Unlike arr[i] = value, it will not stretch the array: [1, 2, 3].with(5, 0) throws RangeError: Invalid index : 5.

// Spread and Rest

The spread operator ... (from Function Parameters) expands an array into separate elements. With arrays, it joins, copies, and passes values:

const q1 = ["Jan", "Feb", "Mar"];
const q2 = ["Apr", "May", "Jun"];

const half = [...q1, ...q2];          // join
const copy = [...q1];                 // copy
console.log(Math.max(...[23, 55, 21]));   // pass as arguments: 55

The same three dots on the left side of = do the opposite: rest collects leftover elements into a new array. The [a, ...rest] on the left is a pattern that unpacks the array (JS Destructuring covers this in full):

let first, rest;
[first, ...rest] = [1, 2, 3, 4];

console.log(first);
console.log(rest);
1 [2, 3, 4]

// Choosing the Right One

You want... Use Returns
To do something with each itemforEachundefined
Each item transformedmaparray, same length
Only some itemsfilterarray, same or shorter
One combined valuereduceanything
The first matchfindone element

// Quick Check

What does this log?

for (const x in ["a", "b"]) {
  console.log(x + 1);
}
Show answer
01 then 11. for...in gives the indexes as strings, so + 1 joins text instead of adding. Use for...of for arrays.

Which method returns a new array with the same length as the original?

  1. filter
  2. map
  3. reduce
  4. forEach
Show answer
B. map makes one new element for each old one. filter can return fewer, reduce returns one value, and forEach returns undefined.

What does this log?

const a = [1, 2, 3];
const b = a.with(1, 9);
console.log(a, b);
Show answer
[1, 2, 3] [1, 9, 3]. with returns a changed copy and leaves the original alone.

// Try It

  1. Click Open Playground. Use map to convert the Celsius temperatures to Fahrenheit
  2. Use filter to keep only the words longer than 4 letters from a sentence split into words
  3. Use reduce to find the average of an array of test scores
  4. Chain filter and map to list the names of students with a GPA of 3.5 or higher
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:42 AM ET