Function Composition
Function composition is combining two or more functions to create a new function. The output of one function becomes the input of the next. This lets you build complex operations from simple, reusable pieces.
const double = x => x * 2;
const addOne = x => x + 1;
// Compose: first double, then addOne
const doubleThenAddOne = x => addOne(double(x));
console.log(doubleThenAddOne(3)); // 7 (3*2 + 1)
Generic Compose Function
You can write a compose utility that combines any number of functions. It processes them from right to left, like mathematical function composition.
function compose(...fns) {
return function(x) {
return fns.reduceRight((acc, fn) => fn(acc), x);
};
}
const process = compose(
x => x.toUpperCase(),
x => x.trim(),
x => `Hello, ${x}!`
);
console.log(process(" world ")); // "HELLO, WORLD!"
Pipe vs Compose
pipe is like compose but reads left to right. Many developers find pipe more readable because it follows the natural order of execution.
function pipe(...fns) {
return function(x) {
return fns.reduce((acc, fn) => fn(acc), x);
};
}
const process = pipe(
x => x.trim(),
x => x.toUpperCase(),
x => `Hello, ${x}!`
);
console.log(process(" world ")); // "HELLO, WORLD!"
Try it Yourself →
Real-World Composition
Composition is great for data processing pipelines, formatters, and middleware systems.
const formatPrice = price =>
`$${price.toFixed(2)}`;
const applyDiscount = (discount) => (price) =>
price * (1 - discount);
const addTax = (taxRate) => (price) =>
price * (1 + taxRate);
const calculateFinalPrice = pipe(
applyDiscount(0.1),
addTax(0.08),
formatPrice
);
console.log(calculateFinalPrice(100)); // "$97.20"
Summary
Composition builds complex functions from simple ones. Use compose (right-to-left) or pipe (left-to-right) to create clean, reusable data processing pipelines.