Write a generic memoize(fn) that caches results by arguments.
Closures + cache-key design + tradeoffs (unbounded cache, key collisions).
Keep a Map keyed by a serialization of args (JSON.stringify for simple args; for a single object arg, a WeakMap is better and lets entries be garbage-collected). Return cached value if present, else compute, store, return. Call out the tradeoffs: a JSON key breaks on functions/circular args and is order-sensitive; an unbounded cache is a memory leak — add an LRU cap for hot paths. Correctness preconditions: memoization is only safe for PURE functions (same args → same result, no side effects) — memoizing a function that reads mutable external state or the clock returns stale answers. Use Map, not a plain object, so keys can't collide with prototype names like 'constructor' and so insertion order is preserved (needed for LRU eviction). For a bounded cache, on a hit re-insert the key to mark it most-recently-used, and when size exceeds the cap delete the first (oldest) key from the Map. React.useMemo is the same idea scoped to a component render, keyed by a dependency array instead of arguments.
Pure, expensive, repeatedly-called functions (parsing, derived computations). This is what React.useMemo does conceptually.