Skip to main content

The structuredClone() function

structuredClone() is a built-in JavaScript function that creates a deep clone of any value, including objects, arrays, Map, Set, dates, RegExp, Blob, File, ArrayBuffer and even cyclic references. The result is a completely independent copy, not another reference to the same object.

Theory

TL;DR

  • structuredClone(value) returns a new, independent deep clone of the value.
  • It preserves Date, Map, Set, RegExp, Error, ArrayBuffer, Blob, File, undefined, NaN and Infinity.
  • It handles cyclic references correctly, where JSON.stringify() throws.
  • It cannot copy functions, class methods or DOM elements, those raise a DataCloneError.
  • A second argument { transfer: [...] } lets you hand over a binary buffer instead of copying it.
  • It works in modern browsers and in Node.js from version 17 onwards.

Quick example

javascript
const user = { name: "Tim", age: 25, skills: ["JS", "React"], meta: { active: true }, }; const copy = structuredClone(user); copy.meta.active = false; console.log(user.meta.active); // true, the original is unchanged

Here structuredClone() produced a new copy, not a reference to the same object, unlike the shallow copy { ...user }, where meta would still be shared.

Syntax

javascript
const clone = structuredClone(value);
  • value is what you want to clone;
  • the function returns a new, fully copied and independent object.

Cloning is recursive: every nested object, array or collection gets its own copy too, so you can mutate the clone at any depth.

The main difference from JSON.parse(JSON.stringify(...))

Deep copying used to be written like this:

javascript
const copy = JSON.parse(JSON.stringify(obj));

But that approach has a lot of limitations:

Data typeJSON methodstructuredClone
Datebecomes a stringkept as a Date
Map, Setlostcopied
undefineddisappearspreserved
RegExp, Errorlostpreserved
NaN, Infinitybecome nullpreserved
Cyclic referencesthrowssupported

In other words, structuredClone() is the reliable and safe deep clone that supports all of these types.

Example with cyclic references

javascript
const obj = {}; obj.self = obj; // a cyclic reference const clone = structuredClone(obj); console.log(clone.self === clone); // true

Previously this kind of cloning would simply throw. The structured clone algorithm remembers the objects it has already copied, so re-entering the same node turns into a reference inside the copy instead of infinite recursion.

Cloning with transfer of binary data

structuredClone takes a second argument, an options object, that lets you transfer (rather than copy) certain objects, for example an ArrayBuffer.

javascript
const buffer = new ArrayBuffer(8); const clone = structuredClone(buffer, { transfer: [buffer] }); console.log(buffer.byteLength); // 0, the original was transferred and detached console.log(clone.byteLength); // 8, the data now belongs to the clone

This behaves like transferable objects in postMessage: the memory is not copied, it changes owner, so the operation stays cheap even for large buffers.

Where it works, and a summary

The function is supported in every modern browser and in Node.js from version 17:

javascript
structuredClone({ test: true }); // works in Node.js 17+
ItemDescription
What it doesDeep clones a value of almost any type
ReturnsA fully independent copy
SupportsDate, Map, Set, RegExp, ArrayBuffer, cyclic references
Does not supportFunctions, DOM elements
CompatibilityModern browsers and Node.js 17+
Equivalent toA safe alternative to JSON.parse(JSON.stringify())

Common mistakes

  • Expecting methods to be copied. Functions are not cloneable: structuredClone({ fn() {} }) throws a DataCloneError. A class instance turns into a plain data object with no prototype.
  • Cloning DOM nodes. structuredClone(document.body) also throws a DataCloneError, document nodes are not serialisable by this algorithm.
  • Confusing it with a shallow copy. { ...obj } and Object.assign({}, obj) copy only the top level, nested objects stay shared.
  • Forgetting about the prototype. The clone gets a plain Object.prototype, so copy instanceof User returns false.
  • Relying on getters and setters surviving. They are evaluated once and the clone receives the resulting value as an ordinary property.
  • Using it in an old runtime. Node.js 16 and below do not have the function, so a polyfill or a hand-written implementation is required there.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.