deepClone from Interview #13 breaks on circular references — it recurses infinitely. Solve it with a WeakMap that tracks already-cloned objects and returns the clone instead of recursing. Then extend to handle Date, RegExp, Map, and Set.
Related deep-dive: Data #1 — Deep Clone & Deep Compare
What is Circular Reference Handling in deepClone()?
The basic deepClone from Interview #13 fails catastrophically on circular references. If obj.self = obj, the recursion enters an infinite loop and eventually overflows the call stack. Solving this means tracking which objects have already been cloned and, when you encounter one again, returning the existing clone instead of recursing.
The data structure for this is a WeakMap from original → clone. Before cloning an object, check if it's already in the map. If so, return the cached clone (this is what breaks the cycle). If not, create a new clone, store it in the map immediately (before recursing into children), then recursively clone the children.
The WeakMap is specifically chosen over Map because:
- It holds weak references — if the original object is garbage collected, the WeakMap entry is automatically removed
- It avoids memory leaks in long-lived clone operations
- It's the same data structure the native
structuredCloneuses internally for this purpose
Once the cycle-breaking mechanism is in place, the interviewer typically extends the question to handle non-JSON types:
Date→new Date(value.getTime())RegExp→new RegExp(value.source, value.flags)Map→new Map(Array.from(value.entries()).map(([k, v]) => [deepClone(k, seen), deepClone(v, seen)]))Set→new Set(Array.from(value).map(v => deepClone(v, seen)))
Each type requires its own branch in the recursion, with the WeakMap tracker threaded through all of them.
Real-world use: circular references are common in DOM trees (parentNode/childNodes), graph data structures (adjacency lists), and state management (parent/child entity relationships). Any general-purpose clone utility must handle them.
The Problem
"Your deepClone from earlier handles plain objects and arrays. Now extend it to handle:
- Circular references (an object referencing itself)
Date,RegExp,Map, andSet- Explain why you use
WeakMap, notMap"
Thought Process
Circular references: When you encounter an object that you've already started cloning, you need to return the clone-in-progress, not start a new clone. A WeakMap<original, clone> tracks this mapping.
Why WeakMap? If the original object is garbage collected, the WeakMap entry is automatically removed. With a regular Map, the entry would keep the original alive, creating a memory leak. For a one-shot clone this doesn't matter, but it's the right habit.
Date/RegExp: Create new instances with the same value. new Date(date.valueOf()) and new RegExp(regex.source, regex.flags).
Map/Set: Create new instances and recursively clone their entries.
Step 1 — Circular Reference Detection
Loading editor...
The key: visited.set(value, clone) happens before recursing into properties. This way, if a property points back to the same object, visited.has(value) returns true and the clone-in-progress is returned.
Step 2 — Handling Date and RegExp
Loading editor...
Step 3 — Handling Map and Set
Loading editor...
Step 4 — Edge Cases
Self-referencing object: obj.self = obj — handled by setting visited.set(value, clone) before recursing.
Mutual reference: A → B → A — both clones reference each other correctly.
Map/Set with object keys: Map keys are deep-cloned too, preserving the structural independence.
instanceof check order: Check Date before Object, check RegExp before Object. All are instanceof Object.
Symbol properties: Object.keys skips symbols. If symbol keys matter, use Object.getOwnPropertySymbols or Reflect.ownKeys.
Full Solution
Loading editor...
What Interviewers Are Testing
- Circular reference handling — tracking visited objects with a WeakMap
- WeakMap vs Map — understanding GC implications of key storage
- Type extension — adding Date, RegExp, Map, Set while keeping the structure clean
- Set-before-recurse order — registering the clone in the WeakMap before diving into properties
Complexity
| Time | Space | |
|---|---|---|
| deepClone | O(N) — each value visited once | O(N) — new copy + O(N) WeakMap entries |
Interview Tips
- Explain why WeakMap — "WeakMap lets the GC collect the original if the clone outlives it. With Map, the clone keeps the original alive forever."
- Set the clone before recursing — "I register the clone in the WeakMap first, then recurse. If a child references the parent, the clone is already in the map."
- Check Date and RegExp before object — "
instanceof Dateandinstanceof RegExpbefore the generic object branch, otherwise they fall into theObject.keysloop and lose their prototype." - Mention what's still missing — typed arrays,
Error,Promise,Function, prototype chain preservation. List them so the interviewer knows you're aware.