A shallow copy duplicates only the top-level structure and keeps nested object references shared, while a deep copy recursively copies everything. Knowing the difference is critical to avoid accidental mutations in state management, React/Angular, and general JavaScript code.
Use this JavaScript interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
Shallow Copy vs Deep Copy in JavaScript (Objects, Arrays, References)Frontend interview answer
This JavaScript interview question tests whether you can explain Shallow copy vs deep copy in JavaScript: what is the difference, connect it to production trade-offs, and handle common follow-up questions.
- Shallow copy vs deep copy in JavaScript: what is the difference explanation without falling back to memorized docs wording
- Deep Copy and Clone reasoning, edge cases, and production failure modes
- How you would answer the most likely JavaScript interview follow-up
The core idea
In JavaScript, objects and arrays are reference types. A “copy” can either:
- Shallow copy: copy only the top-level container, but keep nested objects shared.
- Deep copy: copy everything recursively, so no nested references are shared.
Most bugs around state mutation come from thinking you made a deep copy but actually making a shallow one.
Type | What gets copied | What stays shared | Mutation risk |
|---|---|---|---|
Shallow copy | Only the first level | All nested objects/arrays/functions | High (mutating nested data affects original) |
Deep copy | All levels recursively | Nothing (new references everywhere) | Low (copies are fully independent) |
Shallow copy examples
Common ways to make shallow copies:
const original = {
name: 'Alice',
address: { city: 'Paris' }
};
// Shallow copies:
const a = { ...original }; // spread
const b = Object.assign({}, original);
// Top-level is new:
a !== original; // true
// Nested object is shared:
a.address === original.address; // true
// Mutating nested object affects both:
a.address.city = 'London';
console.log(original.address.city); // 'London' ❗
Deep copy examples
const original = {
name: 'Alice',
address: { city: 'Paris' }
};
// 1) structuredClone (modern, correct for most cases)
const deep1 = structuredClone(original);
// 2) JSON trick (limited!)
const deep2 = JSON.parse(JSON.stringify(original));
// Check:
deep1.address === original.address; // false
deep1.address.city = 'Rome';
console.log(original.address.city); // 'Paris' ✅
Why JSON.stringify is dangerous
It silently breaks or loses:
undefined,Symbol, functions
Date,Map,Set,RegExp
- Circular references (throws)
So it only works for plain data objects.
What about arrays?
Same rules apply. [...arr] and arr.slice() are shallow.
const arr = [{ x: 1 }, { x: 2 }];
const copy = [...arr]; // shallow
copy[0].x = 999;
console.log(arr[0].x); // 999 ❗
Where this matters in real life
- React / Angular / Redux / NgRx state updates
- Undo/redo stacks
- Caching snapshots
- Any place you assume “old state” is immutable
A shallow copy of a nested state tree is not enough.
Performance reality check
- Deep copying large objects is expensive.
- In practice, you often do structural sharing: deep copy only the path you change, keep the rest shared (like Redux/Immer).
This is why libraries like Immer exist.
One-sentence answer
A shallow copy creates a new top-level object but reuses nested references, while a deep copy recursively duplicates everything so changes in one copy never affect the other.
Use this as one explanation rep, then continue with the JavaScript interview questions cluster or a guided prep path.