What is the difference between deep copy and shallow copy?
Both create a copy of an object or array, but differ in how deeply they copy nested values.
Shallow copy — copies the top level only; nested objects are still shared by reference, so changing a nested value affects both. Made with spread or Object.assign.
Deep copy — copies every level, so the copy is fully independent. Made with structuredClone() or a library.
Watch out: spread and Object.assign are shallow — nested objects are not truly cloned.
const original = {
name: 'John',
address: { city: 'NYC', zip: '10001' },
hobbies: ['reading', 'coding']
};
// Shallow copy — nested objects shared
const shallow = { ...original };
shallow.name = 'Jane'; // Does NOT affect original
shallow.address.city = 'LA'; // AFFECTS original!
// Deep copy — JSON method (has limitations)
const jsonCopy = JSON.parse(JSON.stringify(original));
jsonCopy.address.city = 'Chicago'; // Does NOT affect original
// Deep copy — structuredClone (recommended)
const deep = structuredClone(original);
deep.address.city = 'Boston'; // Does NOT affect original
// JSON method limitations
const complex = {
date: new Date(), // Becomes string
fn: () => 'hello', // Lost entirely
undef: undefined, // Lost entirely
nan: NaN, // Becomes null
regex: /test/g // Becomes empty object
};
const jsonBad = JSON.parse(JSON.stringify(complex)); // Lossy!Spread creates a new top-level object but address and hobbies are shared. Modifying shallow.address.city changes original.address.city.
JSON method creates a true deep copy but loses functions, Date objects, undefined, NaN, and regex. structuredClone handles most types correctly (Date, Map, Set) but not functions. It is the modern recommended approach.
Know three methods: spread (shallow), JSON.parse+stringify (deep but lossy), structuredClone (deep, recommended). Show the nested object mutation bug with shallow copy. structuredClone is the modern answer — know its limitations (no functions, no DOM).