DEV Community

Raymon Schouwenaar
Raymon Schouwenaar

Posted on • Originally published at Medium on

How to make a real copy of a JavaScript Array with Objects (without a reference)

It happens a lot that you want to copy a variable, with an Object or Array, to manipulate the data and use it afterward. But when we create an array of users and make a copy in a new variable, like this:

var originalObject = [
  {"first":"Gretchen","last":"Kuphal","email":"greenwolf54@gmail.com","address":"416 Lesch Road","created":"March 1, 2012","balance":"$9,782.26"},
{"first":"Morton","last":"Mayer","email":"salmonsquirrel25@gmail.com","address":"1602 Bernhard Parkway","created":"April 29, 2017","balance":"$6,596.11"},
{"first":"Catalina","last":"Daugherty","email":"Catalina.Daugherty@filomena.name","address":"11893 Kali Vista","created":"October 16, 2008","balance":"$6,372.86"},
{"first":"Orpha","last":"Heaney","email":"turquoisewolf22@gmail.com","address":"8090 Chris Stream","created":"November 21, 2015","balance":"$9,596.26"},
{"first":"Reva","last":"Mohr","email":"Reva.Mohr@oda.net","address":"0291 Kailyn Stravenue","created":"November 6, 2014","balance":"$4,768.37"},
{"first":"Loma","last":"Keeling","email":"turquoisegiraffe09@gmail.com","address":"84460 Samson Knoll","created":"June 13, 2017","balance":"$9,361.16"}
];

var duplicateObject = originalObject;

It will keep a reference from “ duplicateObject ” to “ originalObject ”. This is also called a shallow copy.

To show you that it will keep its reference, we gonna change the first name of the first user in the “ originalObject ”.

originalObject[0].first = "Ray";

Then log the “ originalObject ” and “ duplicateObject ” and the result will show you that both are changed! In a lot of cases, you don’t want this to happen!!

So how do we fix this?

We can do the trick with JSON.stringify and JSON.parse method.

var duplicateObject = JSON.parse(JSON.stringify( originalObject ));

And if we now change the first name of the first user in the originalObject, the duplicate will not change!

originalObject[0].first = "Ray";

Check it via the console to log the “ originalObject ” and “ duplicateObject ”;

Originally published at Raymon Schouwenaar.

Top comments (14)

Collapse
 
nektro profile image
Meghan (she/her)

Does const newArr = oldArr.map(x => x) not work? If it does this would be a lot more efficient as it completely skip the string conversion on both sides.

Collapse
 
alainvanhout profile image
Alain Van Hout

That will work as a 'shallow copy' (in a different meaning than used above), since modifying an item from the original array will also cause a change in the equivalent item in the copied array (since those items are in fact the very same items).

Collapse
 
epilleptics profile image
epilleptics • Edited

You could use the spread-operator to create a deep copy of the Array. E.g.

const duplicateObject = originalObject.map(x => ({...x}));

Thread Thread
 
alainvanhout profile image
Alain Van Hout • Edited

That's a clean way to improve the depths of the copy, but it once again falls short when the object nesting goes down 3 levels instead of 2. To resolve that, you'd have to do a manual deep copy (in whatever succinct way).

The performance of the parse(stringify(x)) approach is notably not that bad, particularly compared to a deep copy (although the former of course copies only data, not functions). For example: jsperf.com/deep-copy-vs-json-strin...

Thread Thread
 
weirdmayo profile image
Daniel Mayovsky

Tests were very helpful. Although I am not intending to run the copy more than once a restart of the app. So this works for me.

Collapse
 
rsschouwenaar profile image
Raymon Schouwenaar

Thanks guys for all the questions and answers! But like Alain said, the oldArr.map(x => x) will keep the reference.

Maybe there are other methods like this, but when you want to remove the reference, then this is the only option that I'm aware of ;-)

Collapse
 
weirdmayo profile image
Daniel Mayovsky

I had to use this thing to create a copy of the array with objects, but objects would be stripped of like 12 unnecessary keys before they are parsed by my other functions. Using it for filtering the array, that is considerably large. This does the job well so far.

Collapse
 
borjalo profile image
Borja Alonso Melero

With lodash method _.cloneDeep is working like a charm

lodash.com/docs/4.17.11#cloneDeep

Collapse
 
mhdajmalik profile image
Muhammed Ajmal • Edited

Hi,

I tried this but has a problem
My object contains a date Property, after Json Stringify, in the copied object, it will come as the string, please give me a solution on this if you have

Collapse
 
ashwamegh profile image
Shashank Shekhar

Thanks man, it worked.

Collapse
 
spicyspices profile image
SpicySpices

Thank you so much dude I was having a major problem with this. I was using arr.slice() and [...arr] but nothing was working. Thanks dude.

Collapse
 
kensixx profile image
Ken Flake

This helped me a lot. I also learned a very important concept. Thank you very much for this!

Collapse
 
pekosog profile image
Israel García

I have two questions
1.- what about performance on very large objects?
2.- what about the spread syntax?

Collapse
 
mmantler1958 profile image
mmantler1958

What if you want to also include real copies of any methods that are in the object?