What Is Memoization in JavaScript?
Learn what memoization is, how to implement a memoize() function, and how it relates to React's useMemo and useCallback hooks.
Expected Interview Answer
Memoization is an optimization technique that caches the return value of an expensive, pure function keyed by its input arguments, so that calling the function again with the same arguments returns the cached result instantly instead of recomputing it.
It works by wrapping the original function with a cache — typically a Map or plain object — that, on each call, first checks whether the arguments have been seen before. If so, it returns the stored result immediately; if not, it computes the result, stores it against that argument key, and returns it. Memoization only produces correct results for pure functions, since it assumes the same inputs always produce the same output with no reliance on external mutable state. In a React context, this same idea appears as useMemo (caching a computed value) and useCallback (caching a function reference) to avoid expensive recalculations or unnecessary re-renders, and React.memo memoizes an entire component’s rendered output based on its props. The tradeoff is memory for speed — an unbounded cache on a function called with many unique arguments can grow indefinitely, so real implementations often need eviction strategies like LRU caching.
- Avoids redundant recomputation of expensive, repeatable calculations
- Trades additional memory for significantly faster repeat calls
- Composable via generic higher-order wrapper functions
- Directly maps to React optimization hooks (useMemo, useCallback, React.memo)
AI Mentor Explanation
Memoization is like an analyst who calculates a bowler’s exact economy rate once for a given spell and writes it on a card instead of recalculating from raw ball-by-ball data every time someone asks. The next time anyone requests that same spell’s economy rate, the analyst just reads the card instantly. Only a genuinely new spell triggers a fresh calculation, which then gets written on its own new card. That compute-once-then-reuse-by-lookup pattern is exactly what memoization does with function results.
Step-by-Step Explanation
Step 1
Wrap the target function
Create a higher-order function that holds a cache (Map/object) and wraps the original pure function.
Step 2
Build a cache key from arguments
Serialize or otherwise derive a unique key from the input arguments (e.g. JSON.stringify for simple cases).
Step 3
Check cache before computing
On each call, look up the key; return the cached value immediately if present.
Step 4
Compute and store on a miss
If the key is not cached, run the original function, store the result under that key, then return it.
What Interviewer Expects
- Understanding that memoization only works correctly for pure functions
- Ability to implement a generic memoize() higher-order function
- Awareness of the memory-vs-speed tradeoff and unbounded cache growth risk
- Connection to React's useMemo/useCallback/React.memo as applied memoization
Common Mistakes
- Applying memoization to impure functions (relying on external state or side effects)
- Using an unbounded cache for functions called with many unique argument combinations
- Confusing memoization with general caching of unrelated data (e.g., HTTP responses)
- Forgetting that naive JSON.stringify keys break for non-serializable arguments like functions or circular objects
Best Answer (HR Friendly)
“Memoization means remembering the answer to an expensive calculation the first time you do it, so if you’re asked the exact same question again, you can just hand back the saved answer instead of redoing all the work. It only works safely when the function always gives the same output for the same input.”
Code Example
function memoize(fn) {
const cache = new Map()
return function (...args) {
const key = JSON.stringify(args)
if (cache.has(key)) {
return cache.get(key) // cache hit, no recomputation
}
const result = fn(...args)
cache.set(key, result)
return result
}
}
function slowSquare(n) {
for (let i = 0; i < 1e8; i++) {} // simulate expensive work
return n * n
}
const fastSquare = memoize(slowSquare)
fastSquare(5) // slow the first time
fastSquare(5) // instant on repeat callsFollow-up Questions
- Why does memoization require the wrapped function to be pure?
- How would you evict old entries from an unbounded memoization cache?
- How does useMemo in React differ from a general-purpose memoize() function?
- What happens if you memoize a function called with object arguments using JSON.stringify as the key?
MCQ Practice
1. What property must a function have for memoization to be safe?
Memoization caches outputs by input, which is only correct if the function has no side effects or external dependencies.
2. What is the main tradeoff memoization introduces?
A memoization cache consumes memory to store past results, trading memory for computation time.
3. In React, which hook memoizes a computed value between renders?
useMemo caches a computed value and only recalculates it when its dependencies change.
Flash Cards
What is memoization? — Caching a function's return value by its input arguments to avoid recomputation.
What kind of function can be safely memoized? — A pure function — same inputs always yield the same output.
Main tradeoff of memoization? — Memory usage in exchange for faster repeated calls.
React equivalents of memoization? — useMemo, useCallback, and React.memo.