I’ve used methods like JSON.parse(JSON.stringify(o))
for deep copying, but I’m concerned about its performance. I’ve also come across non-standard solutions like eval(uneval(o))
(which works in Firefox), but I’m looking for a more universally accepted and efficient approach. Are there any better options for deep cloning an object in JavaScript?
Hey, I’ve worked with a few different methods over the years, and one of the most efficient and modern ways I’ve found to do a JavaScript deep copy is using structuredClone
. It’s natively supported in most modern browsers and handles most data types out of the box, including Maps, Sets, Dates, and even circular references.
const clonedObj = structuredClone(originalObj);
Why it works well:
- It’s fast.
- Built-in (so no extra libraries needed).
- Handles complex objects like Maps and Sets, which can be a pain with other methods.
Limitations:
- The only real downside is that it’s not supported in very old browsers (IE or early versions of Edge), but as of 2024, this is pretty much a safe go-to for any modern browser.
I totally get the concern with performance, especially if you’re looking for a more universally accepted solution. For a robust and widely used approach, I recommend Lodash’s cloneDeep
method. It’s a great alternative when you need deep cloning that’s consistent across browsers, and it covers more edge cases.
import cloneDeep from 'lodash/cloneDeep';
const clonedObj = cloneDeep(originalObj);
Why it’s a favorite:
- It works seamlessly across all browsers.
- Handles tricky cases like functions, class instances, and circular references.
- It’s highly maintained by the community, so you get both reliability and support.
When to use it:
If you’re already working with Lodash, it’s a no-brainer. If not, it’s definitely worth considering for its consistency and thorough handling of edge cases in a JavaScript deep copy.
If you’re more into learning or customizing things for your specific needs, writing your own deep copy function can be a good exercise. It’s simple but provides a lot of flexibility in how you want to handle the copying process.
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (Array.isArray(obj)) {
return obj.map(deepCopy);
}
const copy = {};
for (let key in obj) {
copy[key] = deepCopy(obj[key]);
}
return copy;
}
Why it’s cool:
- It’s a great way to understand how deep copying works under the hood.
- You can easily modify it to handle specific cases as you see fit.
Watch out:
This approach doesn’t handle circular references, special types like
Date
or Map
, or prototype chains (it only works with pure objects). If you need these features, you might want to go with a library solution like Lodash or structuredClone
.