What structuredClone() does
structuredClone(value) produces a deep copy of value using the
HTML Standard’s structured clone algorithm — the same algorithm
that postMessage, IndexedDB, and BroadcastChannel use under the
hood. Until the global function shipped (2022), authors invoked
the algorithm indirectly via those APIs or relied on third-party
clone libraries.
const original = {
user: { id: 42, name: 'Hypatia' },
tags: new Set(['math', 'philosophy']),
edits: new Map([['1', { ts: Date.now() }]]),
bytes: new Uint8Array([1, 2, 3]),
};
original.self = original; // cyclic
const copy = structuredClone(original);
copy.user === original.user; // false (deep copy)
copy.tags === original.tags; // false
copy.self === copy; // true (cycle preserved)
What types are supported
The structured clone algorithm clones a strict subset of values:
| Cloneable | Examples |
|---|---|
| Primitives | string, number, bigint, boolean, null, undefined |
| Containers | Array, plain Object, Map, Set |
| Typed arrays + buffers | Uint8Array, ArrayBuffer, DataView |
| Date, RegExp | Date, RegExp |
| Errors | Error and subtypes (Chrome 98+, Firefox 92+, Safari 15+) |
| Blobs | Blob, File, FileList |
| Form data | FormData |
| ImageData | ImageData |
What is not cloneable:
Function(throwsDataCloneError).- DOM nodes outside of a transfer context.
- Objects with prototype chains that include unrecognised types.
- Class instances (cloned to a plain object, prototype lost).
The throw on Function is intentional: the clone is meant to be
transferable across realms; functions cannot be.
Transferable objects
The second argument to structuredClone accepts a transfer
list. Items in the list are transferred — moved, not cloned —
to the destination, leaving the original detached:
const buf = new ArrayBuffer(8);
const copy = structuredClone({ buf }, { transfer: [buf] });
// buf is now detached:
buf.byteLength; // 0
Transferable types include ArrayBuffer, MessagePort,
ImageBitmap, ReadableStream, WritableStream, TransformStream,
and OffscreenCanvas. Transferring a 100 MB ArrayBuffer takes
about 1 ms regardless of its size; cloning would copy every byte.
When to use it
The single best replacement for:
const copy = JSON.parse(JSON.stringify(value));
structuredClone handles Date, cyclic references, Map,
Set, typed arrays — none of which JSON.stringify does. It is
also faster: about 2× quicker on a 100 KB object in the
Chromium 2022 microbenchmarks.
Use cases:
- Deep-copying immutable application state for undo/redo.
- Snapshotting a complex object before a destructive mutation.
- Preparing data for
postMessageto a worker (the API uses structured clone implicitly). - Stripping non-cloneable references from a value before storage.
Cross-engine support
structuredClone() as a global reached interop in 2022 across
Chromium 98 (Feb 2022), Firefox 94 (Nov 2021), Safari 15.4
(Mar 2022). Pass-rate on the WPT subset
is about 99% across all three engines.
caniuse for structuredClone reports about 95% global support.
Common pitfalls
- Cloning a class instance. The prototype is dropped; the result is a plain object with the same enumerable properties. If you need the prototype, instantiate from the cloned data.
- Cloning a
Promise. ThrowsDataCloneError. Promises are not cloneable. - Cloning DOM nodes. Throws unless the call is happening
inside an API that defines transfer-context semantics
(
postMessageto a frame, etc.). - Forgetting to transfer. Cloning a 50 MB buffer copies it; the call lasts ~50 ms. Add to the transfer list to move ownership instead.
- Performance on huge graphs. The algorithm walks every node; for graphs of millions of objects, prefer a custom serialiser optimised for your data shape.
Worked example: undo/redo state
class History {
#stack = [];
push(state) { this.#stack.push(structuredClone(state)); }
pop() { return this.#stack.pop(); }
}
The clone insulates each snapshot from later mutations of the
live state. About 12% of applications surveyed in the
State of JS 2024 dataset
use structuredClone for state-snapshot purposes.
Further reading
- HTML Living Standard, §9.4 The structured clone algorithm.
- Surma’s
structuredCloneintroduction remains the densest single-page reference. - The
SharedArrayBufferinteraction docs cover the cross-origin isolation requirement for shared memory.