Shallow copy vs deep copy
By FrontendPro Editorial Team Updated 9/26/2026
Answer
A shallow copy duplicates only the top level. Nested objects are not copied — both the original and the copy point at the same inner objects. A deep copy duplicates every level, so the two are fully independent.
const original = { name: "Mai", prefs: { theme: "dark" } };
const shallow = { ...original };
shallow.name = "Nam"; // fine, top level is separate
shallow.prefs.theme = "light";
original.prefs.theme; // "light" — the nested object is shared
const deep = structuredClone(original);
deep.prefs.theme = "blue";
original.prefs.theme; // unchanged
How to make each
Shallow: spread ({ ...obj }, [...arr]), Object.assign({}, obj), Array.prototype.slice().
Deep: structuredClone(obj) is the built-in and the right default. It handles nested structures, Date, Map, Set, typed arrays and circular references.
The JSON trick and why it bites
JSON.parse(JSON.stringify(obj)) is the old approach and silently corrupts data:
JSON.parse(JSON.stringify({
when: new Date(), // becomes a string
fn: () => {}, // disappears
missing: undefined, // disappears
big: 10n, // throws
nan: NaN, // becomes null
}));
It also throws on circular references. Use it only when you know the data is plain JSON.
Note structuredClone cannot clone functions, DOM nodes or class instances — it throws on functions, and a class instance comes back as a plain object without its prototype. For those cases, or for very large structures where performance matters, a library such as Lodash's cloneDeep is the practical choice.
Which one do you need?
Shallow is enough, and cheaper, when the nested values are never mutated — which is the normal situation in React-style immutable updates, where you replace nested objects rather than editing them. Reach for deep copying when you genuinely need to edit a nested structure without affecting the source.
