JavaScript Memoization — Cache Function Results with Examples | TryJS

Learn JavaScript memoization with runnable examples. Speed up pure functions by caching their results, and see how recursive Fibonacci goes from seconds to milliseconds.

Overview

Memoization is an optimization technique that caches the result of a function call so that repeated calls with the same arguments return instantly instead of recomputing. It only works on pure functions — ones whose output depends only on their inputs and which have no side effects. Memoization is the cornerstone of dynamic programming and can turn exponential algorithms into linear ones.

How It Works

Build a wrapper around the function

memoize(fn) returns a new function that keeps a Map of previously-computed results, keyed by the arguments. If the cache has the key, return the cached value; otherwise compute, cache, and return.

Cache keys must be comparable

Simple cases use JSON.stringify(args) as the key. Objects-as-arguments work but have a cost; primitive-only arguments are the fastest case.

Pure functions only

Memoization is only safe for functions whose output depends solely on their input — no reading of external state, no side effects. If the function uses the clock, the filesystem, or random numbers, memoizing it will give wrong answers.

Bounded caches avoid memory blowup

An unbounded cache grows forever. For hot paths, use an LRU cache or periodically clear the Map. For small argument spaces, unbounded is fine.

Common Mistakes

When to Use It

Memoize when a function is pure, expensive to compute, and called many times with a small number of distinct inputs. Classic cases: recursive algorithms (Fibonacci, path-finding), derived selectors in state stores, parsing results for common inputs.

Runnable Example

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

// Slow Fibonacci (exponential)
function slowFib(n) {
  if (n < 2) return n;
  return slowFib(n - 1) + slowFib(n - 2);
}

// Memoized Fibonacci (linear)
const fastFib = memoize(function fib(n) {
  if (n < 2) return n;
  return fastFib(n - 1) + fastFib(n - 2);
});

console.time("slow fib(30)");
slowFib(30);
console.timeEnd("slow fib(30)");

console.time("fast fib(30)");
fastFib(30);
console.timeEnd("fast fib(30)");

console.time("fast fib(100)");
console.log(fastFib(100).toString());
console.timeEnd("fast fib(100)");

Open this example in the TryJS playground to edit and run the code instantly in your browser — no signup needed.

Frequently Asked Questions

What is memoization in JavaScript?

Memoization is caching the return value of a function so that repeated calls with the same arguments skip the computation and return the cached result. It's a general optimization technique and the foundation of dynamic programming.

When should I use memoization?

Use memoization when the function is pure (no side effects, output depends only on input), expensive to compute, and called repeatedly with a bounded set of inputs. Classic examples: recursive algorithms and derived state selectors.

Does memoization work on impure functions?

No. Memoizing a function that reads external state or has side effects gives wrong answers: the cached result is frozen in time, but the 'real' answer may have changed. Only memoize pure functions.

How do I handle object arguments in a memoization cache?

Serialize them to a string key (JSON.stringify) for value equality, or use the object reference itself via a WeakMap if reference equality is what you want. WeakMaps also avoid memory leaks for short-lived objects.