How to copy object in JavaScript

2021.10.29

Introduction

If you are here, reading it is probably because something like this has happened to you. You copied an object, you thought you have two different objects, you modified the copy only to discover that original object is also modified. We are going to learn 3 ways to copy an object in Javascript, but before that we need to introduce shallow and deep copy.

people = {
    1: {
        name: 'John'
    }
}
// {1: {…}}1: {name: 'John'}
copyPeople = people
// {1: {…}}1: {name: 'John'}
copyPeople[1].name = 'Martha'
'Martha'
people
// {1: {…}}1: {name: 'Martha'}
copyPeople
// {1: {…}}1: {name: 'Martha'}

Shallow vs Deep Copy

In JS there are primitive types (undefined, null, boolean, number, string...) and reference type (object). When you create a copy of a primitive type by assigning it to new variable, JavaScript internally copies its value. Therefore below example behaves the way we would expect it.

a = 10
// 10
b = a
// 10
b = 20
// 20
a
// 10

Assigning 20 to b doesn't affect a. Reference types are treated differently, if a was an object, b would be assigned a reference to the object that a is pointing to, instead of copied value, meaning both a and b would point at the same object, so modifying a or b modifies the same object.

Shallow copy means that some values of copied object are still connected with the original object. Deep copy happens when new variable is assigned, it is disconnected from original object and assigned its own values.

Shallow Copy in JavaScript

We have seen one way to shallow copy in the beginning done by assigning people to copyPeople. There are two more ways we can do that (Object.assign and '...'). Using our people example it goes like this.

people = {
    1: {
        name: 'John'
    }
}
// {1: {…}}1: {name: 'John'}

copyPeople = Object.assign({}, people)

copePeople2 = {...people}

assign function copies properties of a source object (people) to a target object (empty object {}).

Deep Copy in JavaScript

To deep copy an object we utilize JSON.stringify to convert original object in a string, then JSON.parse to turn it back into a completely new object. Modifying copyPeople doesn't affect the people because now those are two separate objects.

people = {
    1: {
        name: 'John'
    }
}
{1: {…}}1: {name: 'John'}

copyPeople = JSON.parse(JSON.stringify(people))
{1: {…}}1: {name: 'John'}

copyPeople[1].name = 'Martha'
'Martha'
copyPeople
{1: {…}}1: {name: 'Martha'}

people
{1: {…}}1: {name: 'John'}

Conclusion

We have learnt difference between shallow and deep copy in Javascript and understood how it affects modifying objects. To perform shallow copy we can use Object.assign or ... syntax. To perform deep copy use combination of JSON.stringify to convert object into a string and JSON.parse to create completely new object from given string.