structuredClone performs a deep clone using the structured clone algorithm. Unlike JSON.parse(JSON.stringify(value)), it preserves types such as Date, Map, Set, typed arrays and ArrayBuffer, and it can follow cyclic references. It also powers postMessage between workers and the main thread, including transferables that move ownership instead of copying.
Before you start
You should understand references versus values and why {...obj} is only a shallow copy. This article covers the clone algorithm and transfers; it does not cover serialization formats such as CBOR or custom revivers.
Step-by-step walkthrough
Step 1: Know what the algorithm clones
Expect true deep copies of plain objects and arrays, plus built-in containers (Map, Set, Date, RegExp, Blob, ArrayBuffer and typed arrays). Cyclic and shared references are reproduced, not duplicated. Functions, DOM nodes, class instances with methods, and Symbol keys cannot be cloned and throw a DataCloneError.
Step 2: Detach data with a transfer
Pass { transfer: [buffer] } to move an ArrayBuffer or MessagePort to the clone. Transferring detaches the source: its byteLength becomes 0 and any further access throws. This avoids copying large buffers and is the same mechanism postMessage uses between threads.
Step 3: Respect the boundary
The clone has no shared identity with the original: mutating one never affects the other. But a class instance loses its prototype, so an object cloned from class Session becomes a plain object. Redraw that boundary deliberately: send plain data across it, or rehydrate into the class explicitly.
Worked scenario
Run this with Node.js 17 or later (or a modern browser) to see the deep copy and the transfer.
const original = { count: 1, nested: { seen: false }, when: new Date(0) };
const copy = structuredClone(original);
copy.nested.seen = true;
console.log(original.nested.seen); // false
console.log(copy.when instanceof Date); // true
const buffer = new ArrayBuffer(8);
const moved = structuredClone(buffer, { transfer: [buffer] });
console.log(buffer.byteLength); // 0 (detached)
console.log(moved.byteLength); // 8Walk through the example
The nested object is cloned recursively, so editing copy.nested leaves original.nested untouched. The Date keeps its type, which a JSON round-trip would not. In the second half, the buffer is moved: its bytes now belong to moved, and reading buffer afterwards throws because it is detached. A JSON clone would instead produce a string and lose the binary representation.
Common mistake
Assuming a clone can carry everything. Functions, WeakMap keys, promises and DOM nodes throw a DataCloneError; class methods silently become plain properties or disappear. A related mistake is using JSON.parse(JSON.stringify(value)) and expecting Date, undefined and Map to survive: JSON drops each of them.
Verify the behavior
Mutate the clone and assert the original is unchanged, including nested objects. Include a cyclic reference and confirm both copies still point to their own graph. Assert that a transferred buffer’s byteLength is 0 and that accessing it throws. Try cloning an object with a function property and confirm the expected DataCloneError.
Interview exercise
A worker needs to process a 50 MB typed array. Should the main thread clone it or transfer it, and what is the consequence?
Answer and reasoning
Transfer it. Cloning duplicates the bytes, roughly doubling peak memory and stalling both threads during the copy. Transferring moves ownership in constant time, but the sender’s buffer is detached and must not be used afterwards. If the main thread still needs the data, it should keep a copy or request a result back — the point is to choose deliberately rather than clone by default.
Follow-up discussion
Does structuredClone copy getters? It reads the property value and copies the result, so a getter runs once and the clone holds a plain value. Is it safe for untrusted data? Yes for the types it supports, but a huge or deeply nested payload can still exhaust memory, so validate size and depth before cloning input from outside your process.
Continue learning
Compare shallow and deep copying in JavaScript array copy depth and review the MDN structuredClone reference. Continue with the JavaScript interview questions.