What is the difference between a shallow copy and a deep copy of an object?
A shallow copy duplicates only the top level, so nested objects are still shared with the original. A deep copy duplicates every level, so the two are fully independent. Spread and Object.assign are shallow; structuredClone is deep.
Explain it simply
Photocopying a folder of papers is a shallow copy if one of the papers is a sticky note saying "see locker 12". You now have two folders, but both point to the same locker, so changing what is in the locker changes it for both.
{ ...obj }, Object.assign({}, obj) and arr.slice() copy the top-level values. If a value is a primitive, it is truly copied. If it is an object or array, only the reference is copied, so both copies point to the same inner object.
A deep copy goes all the way down. In modern JavaScript, structuredClone(obj) is the built-in way.
Example
const a = { n: 1, tags: ["x"] };
const b = { ...a };
b.n = 2;
b.tags.push("y");
console.log(a.n); // Output: 1
console.log(a.tags); // Output: ["x","y"]The shallow copy b changed a.tags. A deep copy does not:
const c = structuredClone(a);
c.tags.push("z");
console.log(a.tags); // prints: ["x","y"] (unchanged)
console.log(c.tags); // prints: ["x","y","z"]What to say in the interview
"A shallow copy copies top-level properties, but nested objects remain shared references. A deep copy recursively copies everything. Spread, Object.assign and slice are shallow. For deep copies I use structuredClone, which also handles Dates, Maps and circular references, but not functions."
Common mistakes
- Using spread on state with nested objects and then mutating the nested part.
- Assuming JSON.parse(JSON.stringify(x)) is a perfect deep clone. It drops functions and undefined and turns Dates into strings.