That has changed now.
The platform now offers a built-in function that does deep copying for us: structuredClone()
Even if we use the spread operator, it only goes one level deep. Deeply nested properties are still shallow copied.
Deep copying is the opposite of shallow copying. All the nested properties are copied on an individual basis and whenever a nested property is found, the copying happens recursively, creating an actual copy of that property as well. This results in the copied object not sharing anything with the original object.
Until now, people either relied on Lodash’s cloneDeep() method to achieve deep copying, or the most common hack was:
In fact, its popularity made the V8 engine optimize JSON.parse for making the above statement execute faster.
While it works amazingly well, there are a couple of shortcomings of that method:
- It cannot handle objects that have recursive data structures, it throws an error when working with trees or linked lists
- It discards functions
- It does not work with built-in types like Map, Set, Date, Regexp, or ArrayBuffer. It throws an error if it encounters one of these as a value
And it does exactly what you would assume it to do!
There are a couple of limitations, though:
- Functions are still quietly discarded
- Some values are not clonable, like Error and DOM nodes
- An objects prototype chain is discarded as well, so for class instances, a plain instance of the class will be returned