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

  • pipe applies its functions left to right, in the order listed; a compose helper (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 of add(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.

Taught in these lessons

Updated 2026-09-03