Deep copying is a regular programming task for passing or storing data.
- Shallow copy: Only copies the first level of the object
- Deep copy: Copies all levels of the object
const obj = { name: 'Tari', friends: [{ name: 'Messi'}]};
const shallowCopy = { ...obj };
const deepCopy = dCopy(obj);
console.log(obj.friends === shallowCopy.friends); // ❌ true
console.log(obj.friends === deepCopy.friends); // ✅ false
But all this while we’ve never had a built-in way to perfectly deep copy objects and it’s been a pain.
We always had to lean on third-party libraries for deep copying and keeping circular references.
All that changes now with the new structuredClone()
— an easy and efficient way to deep copy any object.
const obj = { name: 'Tari', friends: [{ name: 'Messi' }] };
const clonedObj = structuredClone(obj);
console.log(obj.name === clonedObj); // false
console.log(obj.friends === clonedObj.friends); // false
Cloning circular references with ease:
const car = {
make: 'Toyota',
};
// 👉 Circular reference
car.basedOn = car;
const cloned = structuredClone(car);
console.log(car.basedOn === cloned.basedOn); // false
// 👇 Circular reference is cloned
console.log(car === car.basedOn); // true
Something you could never do with the JSON
stringify
/parse
hack:
Go as deep as you want:
// ↘️
const obj = {
a: {
b: {
c: {
d: {
e: 'Coding Beauty',
},
},
},
},
};
const clone = structuredClone(obj);
console.log(clone.a.b.c.d === obj.a.b.c.d); // ✅ false
console.log(clone.a.b.c.d.e); // Coding Beauty
Limitations you should know
structuredClone()
is very powerful but it has important weaknesses you should know:
Can’t clone functions or methods
Because of the special algorithm it uses.
Can’t clone DOM elements
Doesn’t preserve RegExp
lastIndex
property
I mean, no one’s cloning regexes but it’s one to note:
const regex = /beauty/g;
const str = 'Coding Beauty: JS problems are solved at Coding Beauty';
console.log(regex.index);
console.log(regex.lastIndex); // 7
const regexClone = structuredClone(regex);
console.log(regexClone.lastIndex); // 0
Other limitations
Important to be aware of them to avoid unexpected behavior when using the function.
Clone some, move
This is a more sophisticated one.
You transfer inner objects from source to clone instead of copying.
Which means there’s nothing left in source to change:
const uInt8Array = Uint8Array.from({ length: 1024 * 1024 * 16 }, (v, i) => i);
const transferred = structuredClone(uInt8Array, {
transfer: [uInt8Array.buffer],
});
console.log(uInt8Array.byteLength); // 0
Overall structuredClone()
is a valuable addition to a developer’s toolkit and makes object cloning easier than ever in JavaScript
11 Amazing New JavaScript Features in ES13
This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.