DEV Community

Cover image for You like 'deep' or 'shallow' copy
Milan Mohapatra
Milan Mohapatra

Posted on

You like 'deep' or 'shallow' copy

Copy process of Primitives and Objects.



Before discussing "deep copy" and "shallow copy" we should discuss how "primitive" and "objects" are getting copied in JavaScript.

  • Primitives are by default independent and they get copy by value.
  • Copy by value means if you assign one primitive variable to another variable or pass a primitive value as an argument, then JVM allocates copy the primitive value and allocates new memory for the copied value. Image description
  • Objects are copied by reference, which means a memory block is allocated once for values of the object, and the memory address or reference is shared in case of assignment and passing as argument.
  • It saves lots of memory due to the pass-by-reference mechanism. Image description

Types of copy in JavaScript

  1. Deep Copy
  2. Shallow Copy

We can only do shallow copy with objects not with primitive.


What is this?

  • In shallow copy, JVM allocates a new memory block and copies the top-level property or value to a new memory block. However, if the original obj contains nested objects, the reference to the nested object is still shared between the original obj and copied obj. The copy is one level deep.
let original = { prop: "value", nested: { prop: "nested value" } };

// Shallow copy using Object.assign()
let shallowCopy = Object.assign({}, original);

// Modifying the nested property in the shallow copy
shallowCopy.nested.prop = "modified value";

console.log(original.nested.prop);   // "modified value"
console.log(shallowCopy.nested.prop); // "modified value"
Enter fullscreen mode Exit fullscreen mode

If we modify the value of the nested object in the copied object it will reflect the original object.

  • In deep copy, JVM allocates memory blocks and recursively copies value and property at every level. It is a completely independent memory block with no reference shared between original and copied objects.
let original = { prop: "value", nested: { prop: "nested value" } };

// Deep copy using JSON methods
let deepCopy = JSON.parse(JSON.stringify(original));

// Modifying the nested property in the deep copy
deepCopy.nested.prop = "modified value";

console.log(original.nested.prop);   // "nested value"
console.log(deepCopy.nested.prop);   // "modified value"
Enter fullscreen mode Exit fullscreen mode

Methods for copy

  1. Array slice method. (Array | Shallow)
  2. Array concat method. (Array | Shallow)
  3. Object assign method. (Object | Shallow)
  4. Spraid operator.(Array / Object | Shallow)
  5. JSON.parse(JSON.stringify()) (Array / Object | Deep)
  6. structuredClone() (Array / Object | Deep)

Difference between deep copy and shallow copy

Deep copy Shallow Copy
Advantages
1. Creates independent objects 1. Generally faster and less resource-intensive
2. Suitable for complex objects 2. Suitable for simple data structures, with no deeply nested objects or references.
Disadvantages
1. More resource-intensive and time-consuming. 1. hallow copying may lead to unexpected behavior when dealing with mutable objects. If the original and copied objects share references to the same nested objects, changes made to those nested objects will be reflected in both the original and copied objects.
2. Handling circular references in deep copy implementations can be challenging and might lead to infinite loops if not managed properly. 2. Shallow copy doesn't handle deeply nested structures well. If there are nested objects or arrays within the copied object, changes to those nested structures will affect both the original and copied objects.

What is the difference between JSON.parse(JSON.stringify()) & structuredClone().

The only difference is structuredClone() can copy object if, object has circular reference but JSON.parse(JSON.stringify()) can't.

Circular Reference?

// Creating circular reference
const objA = {};
const objB = {};

objA.propertyB = objB;
objB.propertyA = objA;

// Now, objA refers to objB, and objB refers back to objA

console.log(objA); // The output will show that objA has a propertyB that references objB
console.log(objB); // The output will show that objB has a propertyA that references objA

Enter fullscreen mode Exit fullscreen mode

Notes: In JS, except primitive type all are considered as objects. That's why I used the word Object which refers to Array and Object.


Correct me if I am wrong!!!

Linkedin | Twitter | GitHub

Top comments (0)