Function Composition
Chaining small, single-purpose functions into a pipeline, each handling one transformation.
const pipe = (...fns) => (input) => fns.reduce((v, fn) => fn(v), input);
Purpose
Function composition builds a larger transformation out of small, single-purpose functions chained together β each one independently testable, instead of one large function doing everything.
Example
const trim = (s) => s.trim();
const toLowerCase = (s) => s.toLowerCase();
const removeExtraSpaces = (s) => s.replace(/\s+/g, ' ');
function pipe(...fns) {
return (input) => fns.reduce((value, fn) => fn(value), input);
}
const normalize = pipe(trim, toLowerCase, removeExtraSpaces);
normalize(' Hello World '); // "hello world"
Behavior notes
pipeapplies its functions left to right, in the order listed; acomposehelper (less common in practice) applies right to left instead β worth checking which convention a library uses before assuming.- Each function in the pipeline should take one value and return one value, of a type the next function in the chain accepts.
- Currying β transforming a multi-argument function into a chain of single-argument functions
(
add(a)(b)instead ofadd(a, b)) β is a related technique that makes partial application (fixing some arguments ahead of time) easy, and often shows up alongside composition in functional-style code.
Common mistakes
- Composing functions with mismatched input/output types, producing a pipeline that only works for some inputs.
- Building an overly long pipeline where a single named function (a βwhy,β not just a βwhatβ) would communicate intent more clearly than a long anonymous chain.
Runtime notes
A coding pattern built on core ECMAScript functions, behaving identically anywhere JavaScript runs.