24 minLesson 14 of 35
Arrays & Objects
Array Methods Mastery: map, filter, reduce
Array Methods Mastery: map, filter, reduce
Modern JavaScript array methods let you process data declaratively. Instead of writing loops manually, you describe what transformation you want and the method handles the iteration. This leads to more readable, composable code.
The Core Three
map — Transform Each Element
// Returns a new array of the same length
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
const squared = numbers.map(n => n ** 2); // [1, 4, 9, 16, 25]
const asStrings = numbers.map(String); // ["1", "2", "3", "4", "5"]
// With objects
const users = [
{ id: 1, name: "Alice", age: 30 },
{ id: 2, name: "Bob", age: 25 }
];
const names = users.map(u => u.name); // ["Alice", "Bob"]
const summaries = users.map(u => `${u.name} (${u.age})`);
// Map with index
const indexed = users.map((user, i) => ({ ...user, rank: i + 1 }));
// [{ id:1, name:"Alice", age:30, rank:1 }, ...]
filter — Keep Matching Elements
// Returns a new array, potentially shorter
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
const odds = numbers.filter(n => n % 2 !== 0); // [1, 3, 5]
const big = numbers.filter(n => n > 3); // [4, 5]
// With objects
const adults = users.filter(u => u.age >= 18);
const activeAdmins = users.filter(u => u.active && u.role === "admin");
// Remove falsy values
const clean = [0, 1, null, 2, undefined, 3, ""].filter(Boolean);
// [1, 2, 3]
// Remove duplicates is better done with Set:
const unique = [...new Set([1, 2, 2, 3, 3])]; // [1, 2, 3]
reduce — Accumulate to Any Value
// reduce(callback, initialValue)
// callback receives: (accumulator, currentValue, index, array)
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15
const product = numbers.reduce((acc, n) => acc * n, 1); // 120
const max = numbers.reduce((acc, n) => n > acc ? n : acc, -Infinity);
// Build an object from an array
const userMap = users.reduce((map, user) => {
map[user.id] = user;
return map;
}, {});
// { 1: { id:1, name:"Alice"... }, 2: { id:2, name:"Bob"... } }
// Group by a property
const byRole = users.reduce((groups, user) => {
const key = user.role;
groups[key] = groups[key] ?? [];
groups[key].push(user);
return groups;
}, {});
// Count occurrences
const wordCount = ["a", "b", "a", "c", "b", "a"].reduce((counts, word) => {
counts[word] = (counts[word] ?? 0) + 1;
return counts;
}, {});
// { a: 3, b: 2, c: 1 }
// Flatten nested arrays
const flat = [[1,2],[3,4],[5,6]].reduce((acc, arr) => [...acc, ...arr], []);
// Same as [[1,2],[3,4]].flat()
Searching & Testing
// find — first element that matches
const alice = users.find(u => u.name === "Alice");
const found = numbers.find(n => n > 3); // 4 (first match)
// findIndex — index of first match
const idx = users.findIndex(u => u.id === 2); // 1
// findLast / findLastIndex (ES2023)
const lastEven = numbers.findLast(n => n % 2 === 0); // 4
// some — does any element match?
const hasAdmin = users.some(u => u.role === "admin"); // true/false
// every — do all elements match?
const allActive = users.every(u => u.isActive);
// includes — does the array contain this value?
numbers.includes(3); // true
numbers.includes(10); // false
users.includes(alice); // true (reference equality for objects)
Sorting
// sort mutates the original array! Use [...arr] to sort a copy
const nums = [3, 1, 4, 1, 5, 9, 2, 6];
const sorted = [...nums].sort((a, b) => a - b); // ascending
const desc = [...nums].sort((a, b) => b - a); // descending
// Sort strings
const names = ["Charlie", "Alice", "Bob"];
names.sort(); // mutates! ["Alice", "Bob", "Charlie"]
names.sort((a, b) => a.localeCompare(b)); // locale-aware
// Sort objects
const sortedUsers = [...users].sort((a, b) => a.age - b.age);
const byName = [...users].sort((a, b) => a.name.localeCompare(b.name));
// Stable sort (guaranteed since Node.js 11 / Chrome 70)
const events = data.sort((a, b) => a.timestamp - b.timestamp);
Reshaping Arrays
const nested = [[1, 2], [3, [4, 5]], [6]];
nested.flat(); // [1, 2, 3, [4, 5], 6] — one level
nested.flat(2); // [1, 2, 3, 4, 5, 6] — two levels
nested.flat(Infinity); // fully flatten
// flatMap = map + flat(1) — very useful
const sentences = ["Hello World", "Foo Bar"];
sentences.flatMap(s => s.split(" ")); // ["Hello", "World", "Foo", "Bar"]
// slice — extract a portion (non-mutating)
numbers.slice(1, 4); // [2, 3, 4] (from index 1, up to but not including 4)
numbers.slice(-2); // last 2 elements
// splice — mutate: remove and/or insert (mutating!)
const arr = [1, 2, 3, 4, 5];
arr.splice(2, 1); // removes 1 element at index 2 → arr is [1, 2, 4, 5]
arr.splice(1, 0, 99); // inserts 99 at index 1 → [1, 99, 2, 4, 5]
Building Arrays
// Array.from
Array.from({length: 5}, (_, i) => i); // [0, 1, 2, 3, 4]
Array.from({length: 5}, (_, i) => (i+1) ** 2); // [1, 4, 9, 16, 25]
Array.from("hello"); // ["h", "e", "l", "l", "o"]
Array.from(new Set([1, 2, 2, 3])); // [1, 2, 3]
// Array.of
Array.of(1, 2, 3); // [1, 2, 3] — unlike new Array(3) which creates 3 empty slots
// fill
new Array(5).fill(0); // [0, 0, 0, 0, 0]
[1,2,3,4,5].fill(0, 2, 4); // [1, 2, 0, 0, 5]
Chaining in Practice
const transactions = [
{ amount: 150, type: "credit", category: "salary" },
{ amount: 50, type: "debit", category: "food" },
{ amount: 200, type: "credit", category: "freelance" },
{ amount: 80, type: "debit", category: "transport" },
{ amount: 30, type: "debit", category: "food" },
];
const foodSpend = transactions
.filter(t => t.type === "debit" && t.category === "food")
.map(t => t.amount)
.reduce((sum, amount) => sum + amount, 0);
// 80 (50 + 30)
const income = transactions
.filter(t => t.type === "credit")
.reduce((sum, t) => sum + t.amount, 0);
// 350
Next lesson: Object Methods & Iteration — working with object properties programmatically.
📱
Get Notes Free →Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises