Photo by Yosuke Ota on Unsplash

On this page

This chapter follows Higher-order functions and callbacks.

These patterns show up in libraries and interview questions; in application code, reach for them when they simplify APIs or performance—not to avoid readable loops.

Immediately invoked function expressions (IIFE)

An IIFE runs a function once at load time, creating a private scope for var and early modules.

const module = (function () {
let secret = 0;
return {
inc() {
return ++secret;
},
};
})();

Before ES modules, IIFEs avoided global pollution and loop-capture bugs with var. Today, prefer import/export; IIFEs remain useful for legacy bundles and tiny script snippets.

Currying

Currying turns a function of several arguments into a chain of functions each taking one argument (or a fixed smaller chunk). It helps partial application and uniform unary APIs.

const add = (a) => (b) => a + b;
add(2)(3); // 5
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return (...next) => curried(...args, ...next);
};
}

Manual currying is verbose; lodash curry or hand-written wrappers are common when arity is stable.

Compose and pipe

Compose applies functions right-to-left; pipe goes left-to-right—same as mathematical composition versus reading order.

const compose =
(...fns) =>
(x) =>
fns.reduceRight((v, f) => f(v), x);
const pipe =
(...fns) =>
(x) =>
fns.reduce((v, f) => f(v), x);
const trimAndLower = pipe(
(s) => s.trim(),
(s) => s.toLowerCase(),
);

Use compose/pipe for pure data transforms; avoid deep stacks when debugging stack traces matters.

Memoize

Memoization caches results keyed by arguments so repeated calls with the same inputs skip work.

function memoize(fn) {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
}

Production memoizers use stronger keys (e.g. first argument identity), LRU eviction, and cache busting for unbounded argument spaces. React’s useMemo applies the same idea to render-derived values.

That completes the Functions and Scope series. For object models and this in prototypes, see Objects in JavaScript.

Search articles

Type a word to search published articles.

Open the search page