What is the difference between shallow and deep copies, and how do you create each?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
A shallow copy duplicates only the top level — nested objects are still shared references. A deep copy duplicates every level so nothing is shared. Spread/Object.assign are shallow; structuredClone is deep.
Detailed explanation
Objects live on the heap and variables hold references, so assignment never copies. Spread ({ ...obj }) and Object.assign() create new top-level containers, but any nested object/array is copied as a pointer — mutating nestedObj.x through either version affects both. Deep copying historically meant JSON.parse(JSON.stringify(obj)), which loses functions, undefined, Dates, Maps/Sets and throws on circular refs. Modern JavaScript ships structuredClone(), which handles all built-in types and cycles correctly (but still not functions). Libraries like Lodash's cloneDeep remain common in older codebases. Choosing depth is a real design decision: shallow copies are cheap and usually right for state updates where you replace nested levels wholesale; deep copies protect against untrusted or deeply mutated input at higher cost.
Example
const original = { meta: { views: 1 } };
const shallow = { ...original };
shallow.meta.views = 99;
console.log(original.meta.views); // 99 — shared!
const deep = structuredClone(original);
deep.meta.views = 42;
console.log(original.meta.views); // 99 — untouched
JSON.parse(JSON.stringify({ d: new Date() })).d; // string, not Date!Interview tip
Demonstrate the shared-reference bug first — it proves you understand *why* — then present structuredClone as the modern answer and note JSON's pitfalls.
Common mistakes
- Believing spread performs a deep copy.
- Recommending JSON round-trip without mentioning Date/undefined loss.