Cloning Objects in JavaScript
Cloning an object means making a copy of an existing object.
It is quite straightforward to copy primitive types such as Number
, Boolean
, etc. It can be done by just assigning the value to a new variable:
The Problem
Things get complicated when dealing with reference types such as Object
, Array
, etc. Copying an object by assignment operator doesn’t copy its value but copies its reference.
When we add an item to the copied array, surprisingly, it gets added to the original array as well. This is because by using assignment operator, we didn’t copy the array values but copied the array reference. Here both the variables are pointing to the same location in memory, and therefore modifying one modifies the other.
So, how can we properly clone an object?
There are several ways to do that which we’ll look into below. Also, keep in mind that there are two types of cloning — deep cloning and shallow cloning.
Deep Cloning
Cloning an object (arrays are objects too) as shown above, creates a deep clone of the original object. This newly minted object is completely independent of the original object.
JSON.parse(JSON.stringify())
isn’t a fancy syntax. We are calling JSON.stringify() method first which converts the object to a JSON string. And then we are passing this JSON string to JSON.parse() method which converts it to a JavaScript object.
We can write the same in multiple steps as shown below:
JSON.parse(JSON.stringify())
performs deep cloning of an object. Deep cloning means that if there are nested objects (objects containing other objects as properties), their values are copied not their references. And this goes on for as many nested levels in the object. This becomes more clear when we look at the example in the next section.
But with JSON.parse(JSON.stringify())
, there will be data loss if the object has Date
s, functions, undefined
, Infinity
, Maps, Sets, or other complex types. In such case, it is better use any library which supports cloning of objects with these types. For example, Lodash’s cloneDeep() method creates a deep clone of an object. Take a look at the library or framework you are already using, it might have such a function.
Shallow Cloning
ES6 introduced Object.assign() method and spread syntax. Both these can be used to perform shallow cloning of an object. Shallow cloning means that if there are nested objects, their references are copied not their values.
This can be sufficient when not dealing with nested objects, as in the example below.
But when cloning an object with nested objects, it is required to create a deep clone of an object to avoid any unintended effects.
Let’s look at an example.
As we can see in the above example, modifying the copy
object’s favorites
property also modified the original person
object’s favorites
property. This is because we created a shallow copy of the original object, not a deep copy.
If we instead create a deep copy as shown below, then modifying the copied object doesn’t affect the original object. The copied object is completely independent of the original object.