A higher-order function takes another function as an argument or returns a function. They are the building blocks of clean, reusable JavaScript.
You can read Higher-Order Functions and try the first 1 exercise on the free plan. Upgrade to unlock the remaining 2 exercises and continue the full lesson flow.
Pro: every unit of every course · unlimited hearts · no weekly limit on assessment attempts
Complete lesson & earn 250 PX
EXERCISE
1A higher-order function is any function that takes another function as an argument or returns a function. You have already used them without knowing it.
A higher-order function is one that takes a function as an argument, returns a function, or both. That is the entire definition, and you have already written both kinds in this unit. The name sounds academic; the thing itself is ordinary and you use it constantly.
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(function (n) {
return n * 2;
});
const big = numbers.filter(function (n) {
return n > 3;
});
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(big); // [4, 5]
map and filter are higher-order functions. So is setTimeout, so is addEventListener, and so is sort. Each one handles a fixed piece of machinery and takes the part that varies as a function.
Writing one is no harder than using one:
function applyToAll(items, fn) {
const result = [];
for (let i = 0; i < items.length; i++) {
result.push(fn(items[i]));
}
return result;
}
const prices = [10, 20, 30];
console.log(applyToAll(prices, (p) => p * 0.9)); // [9, 18, 27]
console.log(applyToAll(prices, (p) => p + 5)); // [15, 25, 35]
applyToAll is map, written out. It owns the loop, the index and the accumulating array, and it knows nothing about discounts or addition. Those arrive as the second argument.
The separation is what makes the function reusable. Compare it with the version where the operation is baked in:
function discountAll(items) {
const result = [];
for (let i = 0; i < items.length; i++) {
result.push(items[i] * 0.9);
}
return result;
}
This works, and it answers exactly one question. Every new operation needs another copy of the same five lines, differing only in the middle one. The higher-order version answers all of them.
Pro Tip: When you notice two functions that differ by a single line, the differing line is usually a parameter waiting to be extracted. That is the whole technique, and it is why higher-order functions show up wherever the same shape of work repeats.
The same extraction works on the condition rather than the transformation, which is filter:
function keepIf(items, test) {
const result = [];
for (let i = 0; i < items.length; i++) {
if (test(items[i])) result.push(items[i]);
}
return result;
}
const ages = [12, 19, 34, 7];
console.log(keepIf(ages, (a) => a >= 18)); // [19, 34]
Structurally identical to the previous function. The only difference is whether the supplied function decides what an element becomes or whether it stays.
HOFs accept or return functions. setTimeout, map, filter are all HOFs. They let you extract changing logic into callbacks while reusing the loop structure (DRY principle).