structuredClone

structuredClone() creates a deep copy of a value, preserving types and references within the value: nested objects stay nested, two references to the same object stay shared in the clone, cycles are handled, and built-in types (Date, RegExp, Map, Set, ArrayBuffer, typed arrays, and more) clone as their own type instead of degrading to plain objects. Unlike JSON.parse(JSON.stringify(value)), nothing is flattened to strings and cycles do not throw.

  • structuredClone(value) returns a deep clone.
  • structuredClone(value, { transfer }) moves ownership of supported binary objects (ArrayBuffers) to the clone instead of copying their bytes.
  • Non-cloneable values — functions, DOM/host objects, symbols as values — throw a DataCloneError.

Usage#

const original = {
  created: new Date(),
  tags: new Set(["a", "b"]),
  meta: new Map([["retries", 3]]),
};

const copy = structuredClone(original);
copy.created instanceof Date; // true
copy.tags instanceof Set; // true
copy.meta === original.meta; // false

Shared references and cycles survive:

const node = { name: "root" };
node.self = node;

const clone = structuredClone(node);
clone.self === clone; // true (cycle preserved in the clone)
clone.self !== node; // true (it is a real copy)
structuredClone(() => {}); // throws DataCloneError

Supported types include objects, arrays, Date, Map, Set, RegExp, ArrayBuffer and typed arrays, Blob, and File.

Differences from the standard#

  • Error objects are not cloneable (cloning one throws), while the standard supports cloning Errors with their message and stack.
  • CryptoKey objects are not cloneable. Cloning a CryptoKey, or an object containing one, throws DataCloneError.
  • The { transfer } option is best avoided: platform binary types can only be transferred in limited ways, so behavior may differ from engines with native implementations. Plain ArrayBuffer transfer works.

Documentation#