Skip to main content
Advertisement

3.3 Array Higher-Order Functions

What are Higher-Order Functions?

Higher-Order Functions are functions that accept functions as arguments or return functions. JavaScript's array higher-order functions replace imperative loops with functional style, making code more concise and readable.


map — Transform

Transforms each element and returns a new array. Original array is unchanged.

const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (original unchanged)

// Transform object arrays
const users = [
{ id: 1, name: "Alice", age: 25 },
{ id: 2, name: "Bob", age: 30 },
];

const names = users.map(user => user.name);
console.log(names); // ["Alice", "Bob"]

// Transform API response
const apiUsers = [
{ user_id: 1, display_name: "alice", email_address: "alice@example.com" },
];

const normalized = apiUsers.map(user => ({
id: user.user_id,
name: user.display_name,
email: user.email_address,
}));

filter — Conditional Filtering

Returns a new array with only elements matching the condition.

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]

const products = [
{ name: "Laptop", price: 1200, inStock: true },
{ name: "Mouse", price: 35, inStock: false },
{ name: "Keyboard", price: 85, inStock: true },
];

const available = products.filter(p => p.inStock);
const affordable = products.filter(p => p.price <= 100);
const bestDeals = products.filter(p => p.inStock && p.price <= 100);

// Remove falsy values
const mixed = ["a", null, "b", undefined, "", "c", false];
const truthy = mixed.filter(Boolean);
console.log(truthy); // ["a", "b", "c"]

reduce — Accumulator

Reduces an array to a single value.

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 15

// Maximum value
const max = numbers.reduce((max, cur) => cur > max ? cur : max, -Infinity);
console.log(max); // 5

// Grouping into object
const words = ["apple", "banana", "avocado", "blueberry", "cherry"];
const grouped = words.reduce((acc, word) => {
const letter = word[0];
acc[letter] ??= [];
acc[letter].push(word);
return acc;
}, {});
// { a: ["apple", "avocado"], b: ["banana", "blueberry"], c: ["cherry"] }

// Sum from object array
const orders = [
{ product: "Laptop", quantity: 1, price: 1200 },
{ product: "Mouse", quantity: 2, price: 35 },
];
const total = orders.reduce((sum, order) => sum + (order.quantity * order.price), 0);
console.log(total); // 1270

find and findIndex

Return the first element (or index) matching the condition.

const users = [
{ id: 1, name: "Alice", role: "user" },
{ id: 2, name: "Bob", role: "admin" },
];

const admin = users.find(u => u.role === "admin");
console.log(admin); // { id: 2, name: "Bob", role: "admin" }

const adminIndex = users.findIndex(u => u.role === "admin");
console.log(adminIndex); // 1

// findLast / findLastIndex (ES2023): search from the end
const numbers = [1, 3, 5, 2, 4, 6, 3, 7];
const lastOdd = numbers.findLast(n => n % 2 !== 0);
console.log(lastOdd); // 7

some and every

Returns boolean from condition checks.

const numbers = [1, 2, 3, 4, 5];

console.log(numbers.some(n => n > 4)); // true
console.log(numbers.some(n => n > 10)); // false

console.log(numbers.every(n => n > 0)); // true
console.log(numbers.every(n => n > 2)); // false

// Validation
const formFields = [
{ name: "name", value: "Alice", required: true },
{ name: "email", value: "alice@test.com", required: true },
{ name: "address", value: "", required: false },
];

const isValid = formFields
.filter(f => f.required)
.every(f => f.value.trim() !== "");

console.log(isValid); // true

flat and flatMap

Flattens nested arrays.

const nested = [1, [2, 3], [4, [5, 6]]];

console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]] (1 level)
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]
console.log(nested.flat(Infinity)); // flatten all

// flatMap: map then flat(1)
const sentences = ["Hello World", "JavaScript is fun"];
const words = sentences.flatMap(s => s.split(" "));
console.log(words); // ["Hello", "World", "JavaScript", "is", "fun"]

// Conditional element adding
const items = [1, 2, 3, 4, 5];
const processed = items.flatMap(n => n % 2 === 0 ? [n, n * 2] : [n]);
console.log(processed); // [1, 2, 4, 3, 4, 8, 5]

Method Chaining

const transactions = [
{ type: "income", amount: 500 },
{ type: "expense", amount: 45 },
{ type: "income", amount: 200 },
{ type: "expense", amount: 120 },
];

const totalExpense = transactions
.filter(t => t.type === "expense")
.map(t => t.amount)
.reduce((sum, amount) => sum + amount, 0);

console.log(totalExpense); // 165

Pro Tips

Implementing map and filter with reduce

const myMap = (arr, fn) => arr.reduce((acc, item) => [...acc, fn(item)], []);
const myFilter = (arr, fn) => arr.reduce((acc, item) => fn(item) ? [...acc, item] : acc, []);

// Single-pass filter + map (more efficient)
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const result = numbers.reduce((acc, n) => {
if (n % 2 === 0) acc.push(n * 2);
return acc;
}, []);
console.log(result); // [4, 8, 12, 16, 20]

Latest Array Methods (ES2023+)

const arr = [1, 2, 3, 4, 5];

// toSorted: immutable version of sort
const sorted = arr.toSorted((a, b) => b - a);
console.log(sorted); // [5, 4, 3, 2, 1]
console.log(arr); // [1, 2, 3, 4, 5] (original preserved)

// toReversed: immutable version of reverse
const reversed = arr.toReversed();
console.log(reversed); // [5, 4, 3, 2, 1]

// with: replace element at index (immutable)
const updated = arr.with(2, 30);
console.log(updated); // [1, 2, 30, 4, 5]
Advertisement