Deep Clone
Introduction
A deep clone creates a new object graph instead of copying only the top-level references. Mutating a nested value in the clone should not mutate the original.
Deep clone questions reveal how well you understand references, recursion, arrays, plain objects, cycles, built-in types, and the limits of shortcuts like JSON serialization.
Why This Matters
Cloning appears in state management, undo stacks, optimistic UI updates, test fixtures, and data normalization. In interviews, it is a practical way to test recursion and edge-case thinking without relying on a framework.
Theory
Shallow vs deep
A shallow copy duplicates the outer container but keeps nested references. A deep copy recursively creates new containers for nested data.
The modern built-in
structuredClone(value) is the best built-in option when available. It supports many built-in types and circular references, but it does not clone functions or DOM nodes. Interviewers still ask for manual implementations because they want to see the algorithm.
JSON shortcut limitations
JSON.parse(JSON.stringify(value)) drops functions, symbols, undefined, Date identity, Map, Set, prototypes, and throws on cycles. It is a shortcut for simple data, not a general deep clone.
Manual recursion
The basic algorithm is: return primitives as-is; clone arrays element by element; clone objects property by property. To support cycles, store source-to-clone mappings in a WeakMap before recursing into children.
Scope your answer
A great interview response states what is supported: plain objects, arrays, dates, maps, sets, and cycles might be included; functions are usually returned by reference.
Visual Diagrams
original.user ----> { name: Ada }
shallow.user -----^ same nested object
deep.user --------> { name: Ada } new nested objectA deep clone breaks nested reference sharing.
Code Examples
Recursive clone for arrays and plain objects
This small version handles nested arrays and plain objects, but not cycles, Map, Set, Date, or custom prototypes.
Cycle-safe cloning with WeakMap
Store the empty clone before cloning children so a cycle can point back to the existing clone.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function deepClone(value) {2 if (value === null || typeof value !== 'object') {3 return value;4 }5 if (Array.isArray(value)) {6 return value.map(deepClone);7 }8 var clone = {};9 Object.keys(value).forEach(function (key) {10 clone[key] = deepClone(value[key]);11 });12 return clone;13}14 15var original = { user: { name: 'Ada' }, scores: [1, 2] };16var copy = deepClone(original);17copy.user.name = 'Grace';18copy.scores.push(3);19 20console.log(original.user.name);21console.log(original.scores.length);22console.log(copy.scores.length);Coding Exercises
Implement a cycle-safe deep clone
HardWrite deepClone(value) that supports primitives, arrays, plain objects, Date, Map, Set, and circular references. Return functions by reference.
Interview Questions
1Why is JSON serialization not a complete deep clone?
It only handles JSON-compatible data. It loses undefined, functions, symbols, prototypes, Date objects, Map, Set, and cannot process circular references.
Follow-ups
- How would you handle cycles?
- When would you use `structuredClone`?
2Why does a cycle-safe clone use `WeakMap`?
A WeakMap lets original objects be garbage-collected when no longer referenced elsewhere. The clone operation should not keep source objects alive only because they were used as bookkeeping keys.
Quiz
1. What must a cycle-safe deep clone do before cloning child properties?
Summary
- Deep clone recursively copies nested containers instead of sharing references.
- `structuredClone` is the modern built-in, but manual implementations are still interview staples.
- JSON cloning is limited to JSON-compatible acyclic data.
- Cycle-safe cloning stores source-to-clone mappings in a `WeakMap`.
Cheat Sheet
Base case: primitives and null return as-is.
Containers: arrays map recursively; objects copy keys recursively.
Cycles: WeakMap original → clone.
Built-in: structuredClone handles many cases.
JSON shortcut: simple data only; no cycles, functions, symbols, prototypes, Map, Set, Date identity.