structuredClone()
The deep copy the language lacked for twenty years. It replaces the JSON round trip and is better in almost every way — but it drops class prototypes and refuses anything it cannot serialise.
Demo
The pair is [original.n.x, copy.n.x] after writing 99 into the COPY nested object. The original still reads 1, which is what makes this a genuine deep copy — do the same with Object.assign or a spread and both would read 99, because those copy the nested reference rather than the nested object. What the demo cannot show through JSON input is everything else structuredClone handles that JSON cannot: cycles, Maps, Sets, Dates and typed arrays.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| value | any | yes | Anything supported by the structured clone algorithm. Functions, symbols, DOM nodes and Error subclass details are not, and throw DataCloneError. |
Return value
any — A deep copy. Handles cycles, Map, Set, Date, RegExp, ArrayBuffer and typed arrays. Throws DataCloneError for functions, symbols and DOM nodes.
Common patterns
const draft = structuredClone(state); draft.items.push(item);
const copy = structuredClone(new Map([["a", 1]]));
Object.assign(Object.create(Object.getPrototypeOf(o)), structuredClone({...o}));
Examples
Pitfalls
structuredClone({onDone: () => {}})
const {onDone, ...data} = obj; structuredClone(data)
class C { hi() {} } structuredClone(new C()).hi
Object.assign(new C(), structuredClone({...instance}))
structuredClone({get n() { return Date.now(); }})
Object.defineProperties({}, Object.getOwnPropertyDescriptors(o))
structuredClone(hugeState)
({...state, items: [...state.items, item]})
When to use
- Deep-copying plain data before mutating it
- Data containing Maps, Sets, Dates, RegExps or typed arrays
- Structures with cycles, which JSON cannot handle
- Anywhere JSON.parse(JSON.stringify(x)) currently appears
- The data contains functions → strip them, or copy manually
- You need the prototype preserved → reconstruct after cloning
- A shallow copy is enough → spread, which is far cheaper
- Very large state on a hot path → copy only what changes
Notes
FAQ
structuredClone, in almost every case. The JSON round trip silently drops undefined, functions and symbols, turns Dates into strings, loses Maps and Sets entirely, and throws on cycles. structuredClone handles all of those correctly or fails loudly.
structuredClone(new Map([["a", 1]])); // a Map JSON.parse(JSON.stringify(new Map([["a", 1]]))); // {}