Before we jump into the methods for doing copy in javascript first let’s understand what is Deep copy and shallow copy in the world of Javascript.
Shallow copy
Shallow copy is also identified by pass by reference in other programming languages.
What is a Shallow copy?
When you make a copy of variable(original source) into another variable(new source) by using assignment operator(=) on that time only the reference address(memory address) of the original variable is copied by into another variable and not the actual value(objects, array, etc). At last, both variables refer to the same value. So when you make any changes in the new variable it will also mutate(Change) the original variable.
Javascript does a shallow copy by default for the non-primitive data type(Object, Array, Functions, Math, etc.). There is no any funda of deep or shallow copy applicable for the primitive data types as they are immutable in javascript. There are basically known 6 primitive data types available.
- Number
- Boolean
- String
- Null
- Undefined
- Symbol
Deep copy
Deep copy is also identified by pass by value in other programming languages.
What is a Deep copy?
When you make a copy of variable(original source) into another variable(new source) by using assignment operator(=) on that time all the values(objects, array, etc) along with the reference address(memory address) of the original variable is copied by into another variable. At last, both variables refer to the different referenced values. So when you make any changes in the new variable it won’t mutate the original variable.
Now, Let’s try to digest this concept with a few examples.
As we can see in the above code snippet, Javascript does a deep copy for primitive data types variable by default. So you don’t have to worry about the shallow or deep copy for primitive datatypes.
Now let’s take the example for non-primitive data types(Object, Array, Set, Functions, etc.).
As you can see here, Javascript does a shallow copy for the object data type automatically. So when I change the name(key) of copiedVal variable it also affects the original variable originalVal and mutates the original source too. This is one of the examples of a shallow copy in javascript. Now, what if you don’t want to mutate the original source that means want to do a deep copy. Then, there are a plethora of methods available in javascript to achieve deep copy.
Let’s dig deep into methods of doing Copy in Javascript.
1. Use assignment(=) operator:
This is the basic operator we use in our day to day life for achieving shallow copy.
This is a straightforward example of doing a shallow copy. As you find in the above image that when I make a change in copiedVal(New variable)then it also mutants the originalVal(Original source).
2. Use JSON.stringify() method:
One of the monolithic and easy ways to do a deep copy in javascript is the use of JSON.stringify(). By using you will able to get a deep copy of non-primitive data type.
JSON.stringify() method quite enough able to provide deep copy. However, there is one disadvantage of using this method is that when you use JSON.stringify on an object which has a function as value then it won’t able to justify the copy operation. As you can see in the above example it has brought out key getAge from copiedVal as it’s type is Function. I would recommend use this method only if your objects have not any key with Function type.
Note: This method provides full deep copy but doesn’t work with those data which have the value of Function type.
3. Use Object.assign():
Object.assign() method provides partial deep copy in Javascript. It won’t able to provide a full deep copy if your object or array has nested data. We can see in the above example if I change the value of address1(nested object) in copiedVal then it also mutates the address of the originalVal.
Note: Object.assign() won’t work effectively when you have a nested data structure.
4. Use spread(…) operator:
spread(…) operator is a new ES6 feature javascript which gives us the ability to do a copy in shorthand and fancy way. I mostly use a spread operator when I want to achieve a partial deep copy.
The spread operator does the same thing as Object.assign() method does. It is also able to do a partial deep copy.
Note: Spread operator won’t work effectively when you have a nested data structure.
5. Use _.CloneDeep():
There are few libraries available likes Lodash, Underscore.js , etc. which come up with lots of methods for doing copy in Javascript.
Note:
- _.cloneDeep() method is befitting for 100% full deep copy in case if you want to achieve it.
2. _.clone() method can be used to achieve a shallow copy.
6. Use your own Custom function:
You can also write your own function based on your requirements to achieve a shallow or deep copy. One key fact using this approach is handling all the edge cases so it won’t break your code. But I’m always skeptical about this approach.
7. Use slice() method:
When you have a data type of Array type and you wan to do a deep copy then the slice() method is a good alternative to do that.
Note: slice() method by itself is not enough to clone a multidimensional array completely. It is also not able to provide a full deep copy.