Published on

Deep Copy vs Shallow Copy in Javascript

Overview

This article aims to explain the differences and usage of deep copy and shallow copy in Javascript.

While programming it is very important to not mutate(change) the original data that we receive. Otherwise it would have unintended consequences. The code might become harder to debug and test while giving undesired side-effects.

What is Mutation ?

Lets understand it nicely by the example below:

Lets create an employee object.

employee.js
const employee = {
name: "yogesh",
city: "Mumbai",
designation: "Backend Developer"
}

We can easily edit or add new properties to the same employee object.

employee.js

employee.city= "Bengaluru"

// updated employee object becomes

const employee = {
name: "yogesh",
city: "Bengaluru",
designation: "Backend Developer",
}

We have now successfully mutated the object. But this is a bad practice as it changes the original data by rewriting on the old data. Historical or earlier data is changed permanently.

We can prevent the mutation by making a deep copy. But before learning about deep copy let's learn what is shallow copy.

What is Shallow Copy ?

Shallow copy copies the reference to the original data location in memory. The new variable which copies the earlier data simply points to a memory location. Same piece of data becomes accessible via multiple variables.

Example:

employee.js
const employee = {
name: "yogesh",
city: "Bengaluru",
designation: "Backend Developer",
}

const newEmployee = employee;
const anotherEmployee = newEmployee;

// All the console log outputs will be same.

console.log(employee)
console.log(newEmployee)
console.log(anotherEmployee)


But what is the problem with Shallow copy ?

Lets change the newEmployee object and see what happens.

employee.js
newEmployee.city = "Delhi"

// printing city for all 3 objects
console.log(employee.city)   // Delhi
console.log(newEmployee.city)   // Delhi
console.log(anotherEmployee.city)   // Delhi

By changing data in one object we change the data for all the 3 objects unknowingly. This is undesired and a bad practice which is avoided in the programming world. We can solve this problem by doing a Deep Copy.

What is Deep Copy ?

Deep copy copies the data from the source memory location and stores it in the new memory location. Any change in data in new memory location will not affect the data from source memory location.

Example:

employee.js
// original source data
const employee = {
name: "yogesh",
city: "Bengaluru",
designation: "Backend Developer",
}

// deep copy 1
const employeeCopy1 = {
name:employee.name ,
city:employee.city ,
designation: employee.designation,
}

// deep copy 2
const employeeCopy2 = {
name:employee.name ,
city:employee.city ,
designation: employee.designation,
}

All the three objects point to a unique and different memory locations here. If we make any changes in any of the object it would not affect or change the original object.

How to safely copy objects ?

There are three methods to copy an object in JavaScript

  1. Using spread syntax (...)
  2. Using Object.assign() method
  3. Use JSON.stringify() and JSON.parse() methods

Syntax for using the above three methods:

employee.js
const employee = {
name: "yogesh",
city: "Mumbai",
designation: "Backend Developer"
}

// Using spread operator
const employee1 = {...employee}

// Using Object.assign() method
const employee2 = Object.assign({},employee)

// Using JSON.stringify() and JSON.parse() methods
const employee3 = JSON.parse(JSON.stringify(employee))

All the 3 methods above to do copying is however not same. Spread Operator and Object.assign() method would produce a shallow copy while JSON.parse and JSON.stringify will produce a deep copy.

Lets take a look at the below example in detail for Deep Copy of Objects.

employee.js
const employee = {
name: "yogesh",
city: "Bengaluru",
designation: "Backend Developer",
}

// deep copy

const deepClone = JSON.parse(JSON.stringify(employee))

// changing data in deep copy
deepClone.city = "Hyderabad"

console.log(employee.city) // Bengaluru
console.log(deepClone.city) // Hyderabad

Summary

  1. Data mutation is a bad practice and must be avoided
  2. Shallow copy will give us the refrence of the original data. Any change in shallow copy will also change the original data
  3. Deep copy will store the copied data to a new memory location. Any change in copy will not affect the original data

References

  1. https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy
  2. https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy
  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
  4. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
  5. https://www.digitalocean.com/community/tutorials/js-json-parse-stringify