Memoization caches function results so repeated expensive pure computations can return faster. The real trade-off is memory growth, stale assumptions, and cache-key correctness, so strong answers explain when memoization helps, when not to use it, and why it can backfire in production.
Use this JavaScript interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
What is memoization in JavaScript?Frontend interview answer
This JavaScript interview question tests whether you can explain JavaScript memoization: when it helps, when it backfires, and cache pitfalls, connect it to production trade-offs, and handle common follow-up questions.
- JavaScript memoization: when it helps, when it backfires, and cache pitfalls explanation without falling back to memorized docs wording
- Memoization and Optimization reasoning, edge cases, and production failure modes
- How you would answer the most likely JavaScript interview follow-up
The Core Idea
Memoization is a performance optimization technique used to make expensive function calls faster by storing (or caching) their results. The next time the function is called with the same arguments, the stored result is returned instead of recalculating it.
The important production question is not just "can I cache this?" but "should I?" This technique is especially useful in recursive computations (like Fibonacci sequences) or functions that are called repeatedly with identical inputs.
// Basic memoization example
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
console.log('Fetching from cache:', key);
return cache[key];
}
console.log('Calculating result for:', key);
const result = fn(...args);
cache[key] = result;
return result;
};
}
// Slow recursive function (Fibonacci)
function slowFib(n) {
if (n <= 1) return n;
return slowFib(n - 1) + slowFib(n - 2);
}
// Memoized version
const fastFib = memoize(slowFib);
console.log(fastFib(10)); // Calculates
console.log(fastFib(10)); // Returns from cache
How It Works
- The function is wrapped in a higher-order function that maintains a cache (usually an object or Map).
- When the function is called, the wrapper checks if the input has been seen before.
- If found in cache, the stored value is returned immediately.
- If not found, the function runs normally, stores its result in the cache, and then returns it.
The key concept: trade space for time — use memory to store results and avoid unnecessary computation.
Aspect | Description | Example |
|---|---|---|
Purpose | Reduce repeated computation by caching results. |
|
Cache Key | A string or serialized form of the input arguments. |
|
Storage | Typically an object or Map used as a lookup table. |
|
Trade-off | Uses extra memory but saves CPU cycles for repeated inputs. | Best when function is called frequently with same parameters. |
Memoization vs. Caching
While both involve storing data for faster future access, memoization is function-specific — it stores function return values based on input arguments. General caching, on the other hand, can apply to data from APIs, databases, or file systems.
In other words:
- Memoization → optimization at the function level.
- Caching → broader concept used in networking, databases, or browsers.
// Using Map for better performance
function memoizeMap(fn) {
const cache = new Map();
return function(...args) {
const key = args.toString();
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
}
const add = (a, b) => a + b;
const memoizedAdd = memoizeMap(add);
console.log(memoizedAdd(2, 3)); // 5 (calculated)
console.log(memoizedAdd(2, 3)); // 5 (cached)
When to Use and When Not To
✅ Use memoization when:
- A function performs expensive or repetitive calculations.
- The same inputs occur frequently.
- The function is pure — it always returns the same output for the same inputs.
🚫 Avoid memoization when:
- The input range is very large (cache will grow uncontrollably).
- The function relies on external state or randomness.
- The computation is cheap (the overhead of caching may outweigh benefits).
Real-World Use Cases
- React’s useMemo() and useCallback(): Prevent re-rendering by memoizing values or functions between renders.
- API call optimization: Cache API responses to avoid fetching the same data multiple times.
- Dynamic programming: In problems like Fibonacci, factorial, or pathfinding (e.g., Dijkstra’s algorithm), memoization avoids redundant recursive calls.
- Machine learning pipelines: Memoizing preprocessing steps for repeated datasets.
// Example: API response caching
async function memoizedFetch(url) {
const cache = memoizedFetch.cache || (memoizedFetch.cache = {});
if (cache[url]) return cache[url];
const response = await fetch(url);
const data = await response.json();
cache[url] = data;
return data;
}
// First call fetches from network, second from cache
await memoizedFetch('https://api.example.com/data');
await memoizedFetch('https://api.example.com/data');
Think of memoization like remembering math homework answers — once you’ve solved a problem, you don’t need to redo it every time someone asks. You just recall the answer instantly.
- Memoization caches function results to avoid recomputation.
- Best for expensive, pure, and repetitive function calls.
- Can be implemented using objects or Maps as cache stores.
- Saves time but uses additional memory.
- Core concept behind performance optimizations in React, Lodash, and Redux selectors.
Use this as one explanation rep, then continue with the JavaScript interview questions cluster or a guided prep path.