Master Deep Cloning in JavaScript with structuredClone()

This article explores the modern JavaScript global function structuredClone() as a robust solution for deep cloning objects, comparing it with traditional spread, JSON methods, and custom recursion, and covering handling of circular references, functions, undefined values, performance benchmarks, supported types, and limitations.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Master Deep Cloning in JavaScript with structuredClone()

Classic interview question: how to implement deep copy.

Common answers use JSON or recursive traversal, testing familiarity with object manipulation. This article introduces another solution: structuredClone(). structuredClone() is a global function introduced in 2022 that enables true deep cloning of JavaScript objects, handling complex structures and circular references that break JSON.stringify() / JSON.parse().

structuredClone illustration
structuredClone illustration

Basic Usage

It creates a genuine deep clone, preserving nested objects and circular references without extra logic, and works in modern environments including Web Workers.

1. Simple Object Clone

Using the spread operator {...obj} creates a shallow copy:

const original = {name: "Alice", details: {age: 25}};
const shallowCopy = { ...original };
shallowCopy.details.age = 30;
console.log(original.details.age); // 30
console.log(shallowCopy.details.age); // 30

The change to shallowCopy.details also affects original.details because only a shallow copy was made.

Deep copy with JSON:

const original = {name: "Alice", details: {age: 25}};
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.details.age = 30;
console.log(original.details.age); // 25
console.log(deepCopy.details.age); // 30

This method cannot clone functions, undefined, or circular references.

Deep copy with structuredClone():

const original = {name: "Alice", details: {age: 25}};
const clone = structuredClone(original);
clone.details.age = 30;
console.log(original.details.age); // 25
console.log(clone.details.age); // 30
structuredClone()

produces a deep clone without the limitations of JSON.stringify().

2. Circular References

The spread operator fails with circular references, causing errors.

JSON also throws a TypeError when encountering circular structures. structuredClone() handles circular references gracefully:

const original = {name: "Alice", self: null};
original.self = original;
const clone = structuredClone(original);
console.log(clone !== original); // true
console.log(clone.self === clone); // true

3. Functions and undefined

Spread copies functions and undefined shallowly, but they are not deep‑cloned.

JSON loses both functions and undefined values. structuredClone() does not clone functions (they become undefined) but preserves undefined values, making it more reliable than JSON for complex objects.

4. Performance

Benchmark with a large array shows structuredClone() is typically faster than the JSON stringify/parse combination and avoids serialization overhead.

const largeArray = new Array(1e6).fill({key: "value"});
console.time("structuredClone");
const clone = structuredClone(largeArray);
console.timeEnd("structuredClone");
console.time("JSON.stringify + JSON.parse");
const jsonCopy = JSON.parse(JSON.stringify(largeArray));
console.timeEnd("JSON.stringify + JSON.parse");

Deep Dive

The global structuredClone() uses the structured cloning algorithm, which can also transfer transferable objects instead of copying them.

Signature: structuredClone(value, { transfer }) value : any value supported by the algorithm.

Supported types include Array, ArrayBuffer, Boolean, DataView, Date, certain Error types, Map, plain objects, primitive types (except Symbol), RegExp (without lastIndex), Set, String, TypedArray, etc.

transfer (optional) : an array of transferable objects whose ownership is moved to the clone, leaving the original empty.

Example of transferring a large Uint8Array:

var uInt8Array = new Uint8Array(1024 * 1024 * 16); // 16 MB
for (var i = 0; i < uInt8Array.length; ++i) { uInt8Array[i] = i; }
const transferred = structuredClone(uInt8Array, { transfer: [uInt8Array.buffer] });
console.log(uInt8Array.byteLength); // 0

The algorithm cannot clone Function objects, DOM nodes, or preserve certain object metadata such as property descriptors, getters/setters, prototype chain, and RegExp lastIndex.

Conclusion

Reliability: Predictably handles circular references, functions, and undefined values.

Efficiency: Faster deep cloning for large data sets without work‑arounds.

Simplicity: One method replaces spread, JSON tricks, and custom deep‑clone functions.

performancedeep cloningstructuredClone
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.