Higher-Order Function Patterns in JavaScript
Common HOF patterns: compose, pipe, curry, partial, memoize. Here is how to implement each.
Higher-Order Function Patterns in JavaScript
Here are the most common higher-order function patterns and how to implement each.
1. compose (Right to Left)
function compose(...fns) { return (x) => fns.reduceRight((acc, fn) => fn(acc), x); } const addOne = (n) => n + 1; const double = (n) => n * 2; const result = compose(double, addOne)(5); // 12 (addOne first, then double) `` ### 2. pipe (Left to Right) ```js function pipe(...fns) { return (x) => fns.reduce((acc, fn) => fn(acc), x); } const result = pipe(addOne, double)(5); // 12 (addOne first, then double) `` `pipe` is like `compose` but left-to-right (more natural to read). ### 3. curry ```js function curry(fn) { return function curried(...args) { if (args.length >= fn.length) return fn(...args); return (...next) => curried(...args, ...next); }; } const sum = curry((a, b, c) => a + b + c); sum(1)(2)(3); // 6 sum(1, 2)(3); // 6 `` ### 4. partial ```js function partial(fn, ...presetArgs) { return (...laterArgs) => fn(...presetArgs, ...laterArgs); } const add = (a, b, c) => a + b + c; const add5 = partial(add, 5); add5(3, 2); // 10 `` ### 5. memoize ```js function memoize(fn) { const cache = {}; return (...args) => { const key = JSON.stringify(args); if (!(key in cache)) cache[key] = fn(...args); return cache[key]; }; } `` ### 6. debounce ```js function debounce(fn, delay) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); }; } `` ### 7. throttle ```js function throttle(fn, delay) { let last = 0; return (...args) => { const now = Date.now(); if (now - last >= delay) { last = now; fn(...args); } }; } `` ### 8. once ```js function once(fn) { let done = false; let result; return (...args) => { if (done) return result; done = true; result = fn(...args); return result; }; } `` ### The Takeaway Common HOF patterns: `compose` (right to left), `pipe` (left to right), `curry` (one arg at a time), `partial` (preset some args), `memoize` (cache results), `debounce` (delay until activity stops), `throttle` (limit rate), `once` (run only once). All rely on closures and first-class functions.
compose applies functions right to left: compose(f, g)(x) = f(g(x)). pipe applies functions left to right: pipe(f, g)(x) = g(f(x)). pipe is more natural to read (first function runs first).
Return a function that collects arguments. If enough arguments are collected (args.length >= fn.length), call the original function. Otherwise, return a new function that collects more arguments. Use recursion.
curry transforms a function into a chain of single-argument functions: f(a)(b)(c). partial presets some arguments and returns a function for the rest: f'(b, c) with a preset. curry is one-arg-at-a-time; partial is some-args-now.
Close over a cache object. Serialize the arguments as a key. If the key is in the cache, return the cached result. Otherwise, call the original function, store the result, and return it. The cache is private to the closure.
compose, pipe, curry, partial, memoize, debounce, throttle, and once. All rely on closures and first-class functions. They are the building blocks of functional programming in JavaScript.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

