structuredClone() is the modern, built-in way to deep copy objects. No more JSON.parse(JSON.stringify()) hacks.
The Old Way (and its problems)
// JSON round-trip — the classic hack
const copy = JSON.parse(JSON.stringify(original));
// Problems:
// ❌ Drops undefined values
// ❌ Drops functions
// ❌ Drops Symbol properties
// ❌ Converts Date to string
// ❌ Converts Map/Set to empty object
// ❌ Throws on circular references
// ❌ Loses prototype chainstructuredClone (Modern Way)
const original = {
name: "Rahul",
date: new Date(),
nested: { deep: { value: 42 } },
set: new Set([1, 2, 3]),
map: new Map([["key", "value"]]),
array: [1, [2, [3]]],
regex: /hello/gi,
blob: new Blob(["data"]),
};
const clone = structuredClone(original);
// ✅ Deep copy — no shared references
clone.nested.deep.value = 99;
console.log(original.nested.deep.value); // Still 42
// ✅ Preserves types
clone.date instanceof Date; // true
clone.set instanceof Set; // true
clone.map instanceof Map; // true
clone.regex instanceof RegExp; // trueWhat structuredClone Supports
- ✅ Nested objects and arrays
- ✅ Date, RegExp, Blob, File
- ✅ Map, Set
- ✅ ArrayBuffer, TypedArrays
- ✅ Circular references (!)
- ❌ Functions (throws error)
- ❌ DOM elements
- ❌ Symbol properties (ignored)
- ❌ Prototype chain (lost)
- ❌ Property descriptors (getter/setter lost)
Circular References
const obj = { name: "circular" };
obj.self = obj; // Circular reference!
// JSON.stringify throws!
JSON.parse(JSON.stringify(obj)); // TypeError!
// structuredClone handles it
const clone = structuredClone(obj); // Works!
clone.self === clone; // true (circular preserved)Performance Comparison
// For 10,000 copies of a medium object:
// structuredClone: ~150ms
// JSON round-trip: ~200ms
// lodash.cloneDeep: ~250ms
// Spread (shallow): ~5ms
// structuredClone is fastest for deep copies!When to Use What
- Shallow copy: spread operator (
{ ...obj }) - Deep copy:
structuredClone() - Copy with functions: manual implementation or lodash.cloneDeep
- Immutable updates: Immer library