How to Deep Copy in JavaScript with structuredClone

The structuredClone() method is a native JavaScript utility designed to create deep copies of complex values, eliminating the need for third-party libraries like Lodash or problematic hacks like JSON.parse(JSON.stringify()). This article explains how structuredClone() operates under the hood using the structured clone algorithm, details the data types it supports, demonstrates how it handles circular references and transferable objects, and outlines its key limitations.

What is structuredClone?

structuredClone() is a globally available function in modern web browsers, Node.js (v17+), and Deno. It accepts a target value and returns a complete, independent duplicate where nested objects, arrays, and other data structures are duplicated in memory rather than copied by reference.

const original = { name: "Alice", details: { age: 30 } };
const copy = structuredClone(original);

copy.details.age = 31;
console.log(original.details.age); // 30 (unaffected)

How the Algorithm Works

Under the hood, structuredClone() uses the Structured Clone Algorithm, an internal HTML standard mechanism originally built for messaging across Web Workers, postMessage(), and IndexedDB.

  1. Recursive Graph Traversal: The algorithm traverses the entire input structure recursively, inspecting every property and value.
  2. Memory Allocation: Instead of copying pointer references, it allocates new memory locations for every encountered composite structure (such as Objects, Arrays, Maps, and Sets).
  3. Graph Mapping for Circular References: The algorithm keeps an internal reference map of previously traversed objects. If it encounters an object it has already cloned in the current traversal path, it points to the newly created clone rather than recursively expanding forever. This natively prevents infinite recursion errors on circular references.
const circularObj = { name: "Loop" };
circularObj.self = circularObj;

const clonedCircular = structuredClone(circularObj);
console.log(clonedCircular.self === clonedCircular); // true
console.log(clonedCircular.self === circularObj); // false

Supported Data Types

Unlike JSON serialization, structuredClone() preserves many built-in JavaScript types:

Transferable Objects

structuredClone() accepts an optional second argument allowing you to transfer ownership of specific resources instead of copying their bytes.

const uInt8Array = new Uint8Array(1024 * 1024); // 1MB buffer
const clone = structuredClone(uInt8Array, { transfer: [uInt8Array.buffer] });

console.log(uInt8Array.byteLength); // 0 (detached/neutered)
console.log(clone.byteLength); // 1048576 (transferred to clone)

Transferring is memory-efficient for large binary payloads because it moves the underlying buffer reference instantly without duplicating memory allocation.

Limitations and Unsupported Types

While powerful, structuredClone() has explicit limitations: