Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

JS Puzzles · Const

Memoization

Memoization caches a function's result for an input so repeated calls can avoid recalculation. In JavaScript, it is commonly implemented as a decorator backed by a Map.

How it works

Memoization wraps a frequently called function and stores each computed result in a Map. Later calls with the same argument read the cached value instead of recalculating it; call/apply-style forwarding can preserve the original receiver and arguments when the wrapper delegates execution.

Syntax

function cachingDecorator(func) { /* return a caching wrapper */ }

Parameters

NameTypeDescription
funcFunctionThe function whose results should be cached.
contextanyThe execution context forwarded to the wrapped function.
argsarray-likeArguments forwarded to the wrapped function.

Returns

A wrapper function that caches results for repeated inputs.

Key points

  • Memoization avoids repeating expensive work by retaining results from earlier calls.
  • A Map is a natural cache because it associates each input key with its computed result.
  • A cache hit is detected before the original function runs.
  • On a hit, the stored value is returned immediately.
  • A cache miss delegates computation to the wrapped function.
  • After computing a missing result, the wrapper records it under the input key.

Common mistakes

  • Caching is useful for repeated calls, but it adds memory usage and is not automatically appropriate for every function.
  • A cache is only correct when reusing an earlier result is valid; functions whose result depends on changing external state can become stale.

Example: Caching a function result

function memoize(fn) {
  const cache = new Map();
  return function (x) {
    if (cache.has(x)) return cache.get(x);
    const result = fn.call(this, x);
    cache.set(x, result);
    return result;
  };
}

const slowSquare = memoize((x) => x * x);
console.log(slowSquare(5));
console.log(slowSquare(5));

The wrapper computes a result once for each argument and returns the cached value on later calls.

When to use it

Avoid repeated computation

An expensive pure calculation receives the same input repeatedly.

Cache recursive subproblems

A recursive algorithm reaches identical subproblems.

Wrap with a decorator

A frequently called function needs behavior added without changing its body.

Interview questions

QHow does memoization work?

A memoization decorator keeps a Map from an argument to the result. On each call it checks the Map, returns a stored value on a hit, and otherwise calls the original function, stores the result, and returns it.

Follow-up: How would you support several arguments? Use a stable compound key or nested Maps, and ensure the key distinguishes every input combination.

QHow can a decorator preserve the wrapped function's context?

The wrapper must forward the call to the original function. func.call(context, ...) supplies an explicit this, while func.apply(context, args) supplies the context plus an array-like argument list.

Follow-up: What can break when forwarding? A wrapper that invokes the function without preserving this can change behavior for methods that read instance state.

QWhat are the main trade-offs?

Memoization trades additional storage for fewer repeated calculations. It is most useful when calls recur with the same inputs and the wrapped function's result can safely be reused.

Follow-up: What policy may be needed for an unbounded cache? Add eviction or an explicit lifetime so retained entries do not grow indefinitely.

  • Map
  • call
  • apply
  • decorator
  • call forwarding

Source: Decorators and forwarding, call/apply - The Modern JavaScript Tutorial. Checked 2026-10-15.