Higher-Order Functions and Function Composition
Higher-Order Functions
A higher-order function is a function that either accepts another function as an argument, returns a function, or both. Array.prototype.map, filter, and reduce are the classic examples, but you can build your own.
// A HOF that returns a function (factory pattern)
function multiplier(factor) {
return (n) => n * factor;
}
const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
// A HOF that accepts a function
function repeat(fn, times) {
for (let i = 0; i < times; i++) fn(i);
}
repeat(console.log, 3); // 0, 1, 2Function Composition
Composition chains functions together so that the output of one becomes the input of the next. A compose utility applies functions right-to-left; pipe applies them left-to-right (which reads more naturally for most people).
// pipe: left-to-right composition
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
const trim = (s) => s.trim();
const lower = (s) => s.toLowerCase();
const noSpace = (s) => s.replace(/\s+/g, "-");
const slugify = pipe(trim, lower, noSpace);
console.log(slugify(" Hello World ")); // "hello-world"Partial Application and Currying
Partial application fixes some arguments of a function in advance. Currying transforms a multi-argument function into a chain of single-argument functions. Both patterns enable reuse and cleaner pipelines.
// Partial application with bind
function add(a, b) { return a + b; }
const add10 = add.bind(null, 10);
console.log(add10(5)); // 15
// Curried add
const curriedAdd = (a) => (b) => a + b;
const add5 = curriedAdd(5);
console.log(add5(3)); // 8
// Useful in pipelines
const prices = [10, 20, 30];
const addVAT = curriedAdd(0.2); // not quite right — illustrative
const withTax = prices.map((p) => p * 1.2);Higher-order functions and composition are the foundation of functional programming in JavaScript. Libraries like Ramda and lodash/fp make heavy use of these patterns. Even without a library, inlining small pipe or compose helpers keeps transformation logic clean and testable.