Mastering Deep Cloning in JavaScript with structuredClone()
This article explains how the new global function structuredClone() provides a reliable, fast, and simple way to deep‑clone JavaScript objects—including nested structures, circular references, and undefined values—outperforming traditional JSON or manual recursion methods.
Classic interview question: how to achieve deep copy.
Common answers use JSON.stringify/parse or recursive traversal; this article introduces another solution: structuredClone().
structuredClone()is a global function introduced in 2022 that enables deep cloning of JavaScript objects, handling complex structures and circular references that JSON methods cannot.
Basic Usage
It creates a true deep clone, preserving nested objects and circular references without extra logic, and works in modern environments including Web Workers.
1. Simple Object Clone: Basics
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); // 30The spread operator only copies the top level; changes to nested objects affect the original.
Using JSON.stringify() + JSON.parse() creates a deep copy but cannot handle functions, undefined, or circular references.
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); // 30Using structuredClone() for deep copy:
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()preserves structure without the limitations of JSON methods and can handle circular references and undefined.
2. Circular References
The spread operator cannot handle circular references and throws an error.
const original = {
name: "Alice",
self: null
};
original.self = original; // circular reference
const shallowCopy = { ...original }; // TypeErrorJSON methods also fail with circular structures.
const jsonCopy = JSON.parse(JSON.stringify(original)); // TypeError structuredClone()easily clones objects with circular references:
const original = {
name: "Alice",
self: null
};
original.self = original;
const clone = structuredClone(original);
console.log(clone !== original); // true
console.log(clone.self === clone); // true3. Functions and undefined
Spread operator copies functions and undefined shallowly.
const original = {
name: "Alice",
greet: () => "Hello!",
value: undefined
};
const shallowCopy = { ...original };
console.log(shallowCopy.greet()); // "Hello!"
console.log(shallowCopy.value); // undefinedJSON.stringify cannot serialize functions or undefined, so they are lost.
const jsonCopy = JSON.parse(JSON.stringify(original));
console.log(jsonCopy.greet); // undefined
console.log(jsonCopy.value); // undefined structuredClone()also does not clone functions but retains undefined values, making it more reliable than JSON methods.
4. Speed and Efficiency
For large data sets, structuredClone() is generally faster than the JSON approach.
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 clone algorithm to deep copy any supported value. It also supports transferring transferable objects instead of copying them.
structuredClone(value, { transfer })value – the object to clone; any type supported by the algorithm.
Supported JavaScript types include Array, ArrayBuffer, Boolean, DataView, Date, certain Error types, Map, plain Object literals, 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 inaccessible.
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); // 0The algorithm is used internally for data transfer between workers, IndexedDB, etc., and avoids infinite loops by tracking visited references.
Limitations: Functions, DOM nodes, and certain object metadata (e.g., property descriptors, getters/setters, prototype‑chain properties) cannot be cloned and will throw DATA_CLONE_ERR.
Conclusion
The advantages of structuredClone() are:
Reliability: predictable handling of circular references, functions, and undefined values.
Efficiency: faster deep cloning for large datasets without serialization overhead.
Simplicity: a single built‑in method replaces spread syntax, JSON tricks, or custom deep‑clone functions.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
