Higher Order Functions
This lesson explains Higher Order Functions with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.
ES6+ Higher Order Functions Overview
A higher-order function is a function that either takes another
function as an argument, returns a function, or both. In JavaScript,
functions are first-class values, so they can be passed around like
numbers, strings, or objects.
Higher-order functions power many core JavaScript patterns, including
array methods such as map(), filter(), and
reduce(), event handlers, middleware, and reusable
utility wrappers.
| Feature | Description |
| Definition | Function that works with other functions |
| Can Accept | Functions as arguments |
| Can Return | New functions |
| JavaScript Trait | Functions are first-class citizens |
| Common Examples | map(), filter(), setTimeout() |
| Common Uses | Callbacks, wrappers, composition, reuse |
Basic Higher Order Function Example
function greet(name, formatter) {
return formatter(name);
}
const shout = (name) =>
`HELLO, ${name.toUpperCase()}!`;
const whisper = (name) =>
`hello, ${name.toLowerCase()}...`;
console.log(
greet("Alex", shout)
);
console.log(
greet("Alex", whisper)
);
The greet function receives another function as an
argument and uses it to format the result.
How Higher Order Functions Work
Because functions are values in JavaScript, you can store them in
variables, pass them to other functions, and return them from
functions.
| Step | Description | Example |
| Define Function | Create a reusable callback or wrapper. | const double = x => x * 2 |
| Pass Function | Send it into another function. | apply(numbers, double) |
| Execute Logic | Higher-order function runs the callback. | callback(value) |
| Return Result | Get transformed or processed output. | result |
| Reuse Pattern | Apply same logic to different callbacks. | Flexible utilities |
Functions as Arguments
function repeat(
times,
action
) {
for (let i = 0; i < times; i += 1) {
action(i);
}
}
repeat(3, (index) => {
console.log(
`Run ${index + 1}`
);
});
Callback functions let you customize what happens inside a reusable
control-flow function.
Functions That Return Functions
function createMultiplier(factor) {
return function (number) {
return number * factor;
};
}
const double =
createMultiplier(2);
const triple =
createMultiplier(3);
console.log(double(10));
console.log(triple(10));
Returning functions is useful for creating specialized utilities
from a general pattern.
Array Methods as Higher Order Functions
const prices = [10, 25, 40, 15];
const discounted =
prices.map((price) => price * 0.9);
const expensive =
prices.filter((price) => price >= 20);
const total =
prices.reduce(
(sum, price) => sum + price,
0
);
console.log(discounted);
console.log(expensive);
console.log(total);
Built-in array methods are some of the most common higher-order
functions in JavaScript.
Function Wrapper Example
function withLogging(fn) {
return function (...args) {
console.log(
"Calling function with",
args
);
const result =
fn(...args);
console.log("Result:", result);
return result;
};
}
const add = (a, b) => a + b;
const loggedAdd =
withLogging(add);
console.log(
loggedAdd(4, 6)
);
Wrapper functions add cross-cutting behavior such as logging,
timing, validation, or error handling around another function.
Function Composition
const addTax = (price) =>
price * 1.18;
const applyDiscount = (price) =>
price * 0.9;
const formatPrice = (price) =>
`$${price.toFixed(2)}`;
function compose(...fns) {
return (value) =>
fns.reduce(
(result, fn) => fn(result),
value
);
}
const calculatePrice =
compose(
formatPrice,
addTax,
applyDiscount
);
console.log(
calculatePrice(100)
);
Composition combines small functions into a pipeline, which is a
common functional programming pattern in modern JavaScript.
Event Handlers as Callbacks
const button =
document.querySelector("#save-btn");
function handleSave(event) {
event.preventDefault();
console.log("Saving data...");
}
button?.addEventListener(
"click",
handleSave
);
Event listeners are a real-world example of passing functions into
another function to run later when an event happens.
Higher Order Functions with Arrow Functions
const users = [
{ name: "Alex", active: true },
{ name: "Sam", active: false },
{ name: "Riya", active: true }
];
const activeNames =
users
.filter((user) => user.active)
.map((user) => user.name);
console.log(activeNames);
Arrow functions work especially well as short callbacks in
higher-order array operations.
Common Higher Order Function Patterns
| Pattern | Description | Example |
| Callback | Pass function to run later | setTimeout(fn, 1000) |
| Factory | Return specialized function | createMultiplier(2) |
| Wrapper | Add behavior around function | withLogging(fn) |
| Iterator | Process collections | array.map(fn) |
Common Higher Order Function Use Cases
- Transforming arrays with
map(), filter(), and reduce(). - Handling events and asynchronous callbacks.
- Creating reusable function factories.
- Adding logging, timing, or validation wrappers.
- Building middleware in Express and similar frameworks.
- Sorting and comparing with custom comparator functions.
- Designing composable utility pipelines.
Higher Order Function Best Practices
- Keep callback functions small and focused.
- Use descriptive names for functions passed as arguments.
- Prefer arrow functions for short inline callbacks.
- Return functions only when it improves reuse.
- Avoid deeply nested callback chains when async/await is clearer.
- Document what arguments a callback receives.
- Compose small functions instead of writing one large function.
Common Higher Order Function Mistakes
- Creating callback hell with too many nested functions.
- Passing functions without understanding their parameters.
- Overusing higher-order abstractions for simple logic.
- Forgetting to return values inside callbacks when needed.
- Using anonymous callbacks everywhere with unclear intent.
- Confusing a function factory with immediate execution.
- Not handling errors inside wrapped or composed functions.
Key Takeaways
- Higher-order functions take functions as arguments or return functions.
- JavaScript functions are first-class values.
- Array methods such as
map() and filter() are common examples. - Callbacks, wrappers, and factories are core HOF patterns.
- Higher-order functions help you write reusable and composable code.
Pro Tip
If you use map(), filter(), or
reduce() regularly, you are already working with
higher-order functions every day.