DEV Community

Cover image for Shallow Copy and Deep Copy

Shallow Copy and Deep Copy

AditiJ on June 06, 2022

Table of Contents Introduction Shallow Copy Deep Copy Summary References Introduction Good day, folks! Often times we wan...
Collapse
 
lexlohr profile image
Alex Lohr

I believe you misunderstood those terms. First of all, there are 3 concepts, not two:

  • reference copy: only the reference to an object is assigned to another variable
  • shallow copy: the highest level enumerable properties of an object are copied into a new object
  • deep copy: the object properties are recursively copied into a new object
const obj = { x: 1, y: { a: true, b: false } };
const refCopy = obj;
const shallowCopy = { ...obj };
const deepCopy = structuredClone(obj);
// changing the topmost level:
obj.x = 2;
console.log(refCopy.x, shallowCopy.x, deepCopy.x) // 2, 1, 1
obj.y.b = true;
console.log(refCopy.y.b, shallowCopy.y.b, deepCopy.y.b) // true, true, false
Enter fullscreen mode Exit fullscreen mode

Also, you shouldn't use JSON.parse/stringify to deep copy objects. It's neither the safest way nor should it be recommended. You'll lose some data (e.g. Date, Function, RegExp), have a high chance of errors (e.g. using Symbols, recursive references, etc.) and have a rather bad performance penalty compared to structuredClone.

Collapse
 
aditi05 profile image
AditiJ

Thanks for pointing it out! I probably should have just clarified a bit more.
I have edited it and hope it's a little better now.
Thanks again!

Collapse
 
supportic profile image
Supportic • Edited

You probably mix things up here or maybe I understood it wrong.

Common methods like Array.concat(), Array.from(), Object.assign(), etc creates a shallow copy.
Shallow copy method creates a copy where the source and the copied variable reference remain the same.

let count = [2, 4, 5, 6, 7, 8, 9, 13];
let count2 = Array.from(count);
count2[8] = 14;
console.log(count); // [2, 4, 5, 6, 7, 8, 9, 13]
console.log(count2); // [2, 4, 5, 6, 7, 8, 9, 13, 14]
Enter fullscreen mode Exit fullscreen mode

Shallow copies are non-reference copies but only for the first level in case of non-primitive types like object or arrays. JSON.parse(JSON.stringify(obj)) is also not the ultimate solution because it fails for some types which cannot be parsed like NaN or Infinity [ref]
And you list the spread operator under the headline deep copy but it's also a shallow copy.

Collapse
 
uponthesky profile image
UponTheSky

I guess JS's way of dealing with objects so messy. Why doesn't it have any explicit function like Python's "deepcopy"? Relentlessly nuisances come up and people have to make workarounds like ones mentioned here. Gross...!

Collapse
 
mat3uszkek profile image
Mateusz Skrobiś
Collapse
 
uponthesky profile image
UponTheSky

Oh, I gotta check this out thanks!

Collapse
 
bias profile image
Tobias Nickel

I sometimes used the stringify and parse method too. Underscore and lodash library have deepclone methods.

Once I implementes a kind of ORM. it had query batching. and I wanted to every client to receive a copy if the data. I implemented my own deepclone. It was much faster than underscode. the reason is not that I am so smart, but that my cloneFunction did not need to handle circular objects.

i consider stringify amd parse as quick and dirty, but totally valid option, because you can change the implemebtation down the road, when you get new requirements, such as more performance, more datatypes, or just make it look more professional.😉

Collapse
 
fuzenco profile image
fuzenco

Thank you. This helps me understand a problem I ran into a while back. As someone who’s not really versed in JS, my situation was frustrating. I should take the time and study JS starting from its foundation. Do you recommend any good books/sites?

Collapse
 
aditi05 profile image
AditiJ

Absolutely! It would be best if you spent some time with JS before moving to any framework. Build small projects, read basic stuff off MDN, and you are good to go!

Collapse
 
shubhamkumar648 profile image
Shubham Kumar

Well Articulate Aditi, Learn a lot

Collapse
 
maitrakhatri profile image
Maitra Khatri

Learnt something really important and cool today. Knew the spread operator thing but didn't know the technical name and reason. Thank you for this !! Very simply explained.

Collapse
 
aditi05 profile image
AditiJ

Thank you, Maitra! Glad, it was helpful! :)

Collapse
 
curiousdev profile image
CuriousDev

I think, depending on what you want to achieve, you should create your own copy function. This way you can decide for every reference, if it has to be cloned (new object) or be kept (as a reference).

Collapse
 
amulgaurav profile image
Amul Gaurav

This is very insightful. Got surprised after seeing how spread operator can affect in two different ways.

Thank you very much Aditi! Can you point some resources which you've used to write this super informative article.

Collapse
 
mohammadparsajavidi profile image
mohammadparsa-javidi

That was so great 👌