DEV Community

Cover image for Copy Objects Ways in JavaScript

Copy Objects Ways in JavaScript

Fatemeh Paghar on March 16, 2024

To copy objects in JavaScript, you typically have three options: using the assignment operator (=) for reference copying, performing a shallow copy...
Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

You missed structuredClone.

Collapse
 
fpaghar profile image
Fatemeh Paghar

In JavaScript, the structuredClone() method is used to create a deep copy of a JavaScript object, including nested objects and arrays. This method is similar to JSON.parse(JSON.stringify(object)), but it can handle more complex data types such as Date, RegExp, Map, Set, and cyclic object references, which are not supported by JSON.stringify().

const originalObject = {
  name: 'John',
  age: 30,
  hobbies: ['reading', 'hiking'],
  address: {
    city: 'New York',
    country: 'USA'
  }
};

// Create a deep copy of the original object
const clonedObject = structuredClone(originalObject);

console.log(clonedObject);

Enter fullscreen mode Exit fullscreen mode
Collapse
 
jmpp profile image
J.M. Cléry • Edited

⚠️ Moreover JSON.parse and stringify are very bad for performance. (Incorrect. See discussion below)

Totally agree with the first comments that structuredClone should be the only way in modern codebases to deep clone objects. If you need alternatives, you can use libraries for that (e.g. _.cloneDeep())

Collapse
 
htho profile image
Hauke T.

Performance of JSON.parse(JSON.stringify(obj)) vs. structuredClone(obj) depends on the kind of data you want to clone.

While for more (almost) shallow data the JSON approach is faster, for deeply nested data structuredClone(obj) becomes more performant:

measurethat.net/Benchmarks/Show/30...

The test is very deeply nested, but plausible.

As annoying as this is - there is no silver bullet (performance-wise).
You need to know what kind of data your application will handle, you need to test your solution based on your knowledge about the target audience and their hardware.

Thread Thread
 
mamohsen profile image
Mahmoud Abdel Mohsen

I guess you are right @htho , structuredClone(obj) seems faster in almost all cases unless the data was utterly nested (an edge case).

However, for edge cases I wouldn't use JSON.parse(JSON.stringify(obj)) either. I'd rather stay with structuredClone(obj) for a safer copy option.

jsbm 100 copies
jsbm 1 copy

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Are you sure? Last time I checked structuredClone was dramatically slower than parse and stringify.

measurethat.net/Benchmarks/Show/18...

Thread Thread
 
jonrandy profile image
Jon Randy 🎖️ • Edited

Yup, structuredClone does seem much slower.

Thread Thread
 
jmpp profile image
J.M. Cléry • Edited

You are correct, I'm sorry (comment above edited).
I remembered a discussion where I heard that JSON.stringify was significantly a slow approach to deep clone objects. That misled me doing the comparison with structuredClone.
Thank you for the rectification.

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐

Same thing bit me, I presumed it would be faster and wasted a couple of days refactoring some things (across workers etc) ended up with the "dance" just being way faster, even coping with circular references etc. Frustrating and I was pretty surprised.

Collapse
 
victorz profile image
Victor Zamanian

Honestly very odd that this isn't edited in the main article as the main option now. It should completely replace the JSON.stringify dance. That can be completely forgotten for this purpose. Not for serialization of course, but in this context it shouldn't be recommended anymore.

Collapse
 
miketalbot profile image
Mike Talbot ⭐

I abandoned it because it's way slower. It has some useful other capabilities, but I find I don't need them. In my tests, structured clone was way too slow.

Thread Thread
 
victorz profile image
Victor Zamanian

Structured clone is way slower than stringify? I mean it should be somewhat slower because it's more complete and has more logic. How much we talking? A benchmark coverage would be interesting to read. 👍

Thread Thread
 
miketalbot profile image
Mike Talbot ⭐ • Edited

Jon and I linked benchmarks in other comments. For me it is between 42% and 45% slower. I copy a decent number of simple objects, 1/2 the speed is impactful. I do have cases with circular references etc., these are a reasonable candidate for structured clone, I find that an adapted stringify is more handy though, I can then store things and restore them from persistent storage.

Mine, Jon's

Collapse
 
jangelodev profile image
João Angelo

Hi Fatemeh Paghar,
Your tips are very useful
Thanks for sharing

Collapse
 
mynameisnextstep profile image
Islam • Edited

The overall pros of JSON.parse performance wise is that the runtime ready to deal with that better since the JSON like structure is a well-suitable and "recognizable" for the runtime and underlying mechanisms of working with it are nicely optimized.

Collapse
 
starcradle101 profile image
Hoon Kang

Thank you for all the posts and discussions! While I was already familiar with shallow copying an object, I hadn't known about creating deep copies until now. I've learned several approaches, along with their pros and cons.
Your post is a lot helpful! 👍🏻

Collapse
 
xuho profile image
Nguyen Xuan hoa

With nested object, we can use recursion and Object.assign() or Spread Operator to make deep copy too :)

Collapse
 
adya_kalhari profile image
Adya Kalhari

This is a great article on the different ways to copy objects in JavaScript! I particularly liked the explanation of reference copies, shallow copies, and deep copies. I also found the comparison of JSON.parse() and JSON.stringify() with structuredClone() to be very informative.

Here's a link to my blog post on object copying in JavaScript, which goes into more detail here.

I hope this is helpful!

Collapse
 
nicholasbalette profile image
Nicholasbalette

Refreshing