Memoize
Write memoize(fn) returning a function that behaves identically but never recomputes for arguments it has already seen.
The returned function also exposes getCallCount(), reporting how many times the original actually ran.
Examples
const sum = memoize((a, b) => a + b);
sum(2, 2); // 4, computed
sum(2, 2); // 4, from cache
sum.getCallCount();1Constraints
- Arguments are JSON-serialisable
Notes
- A cached `0`, `false` or `undefined` is still a cached value — check whether the key exists, not whether the value is truthy.
- The harder version (LeetCode 2630) keys on argument identity, which rules out JSON.stringify entirely.
Hints
Editorial: Memoize
Trading memory for time
Memoisation is a cache keyed by arguments. The interesting parts are not the caching but the two places it quietly goes wrong.
Approach
A Map from a key derived from the arguments to the result.
Implementation
function memoize(fn) { const cache = new Map(); let callCount = 0; const memoized = function (...args) { const key = JSON.stringify(args); if (cache.has(key)) return cache.get(key); callCount += 1; const value = fn.apply(this, args); cache.set(key, value); return value; }; memoized.getCallCount = () => callCount; return memoized; }
Worth knowing
Check for the key, not the value. if (cache.get(key)) recomputes every cached 0, false, null and undefined. cache.has(key) is the correct test, and the suite checks it with a function that returns 0.
JSON.stringify is a lossy key. Key order changes the string, so {a:1,b:2} and {b:2,a:1} become different entries; functions and undefined vanish; two distinct objects with the same shape collide. The harder follow-up (LeetCode 2630) keys on argument identity using a tree of Maps, one level per argument, which is exact but never releases what it holds.