Shallow copy
When we create a copy of any object and some fields of original object are referencing to other objects, then just the reference address are copied to the new object. So if you will change something in the copied object then it will change in the original object and vice versa. Let’s see some examples.
For Objects
const phoneObj = {model: 'Apple', version: 'iPhone X'}; const copyObj = phoneObj; copyObj.model = 'Samsung'; console.log(phoneObj); // {model: 'Samsung', version: 'iPhone X'} console.log(copyObj); // {model: 'Samsung', version: 'iPhone X'}
For Arrays
const phones = ['Apple', 'Samsung', 'Nokia', 'OnePlus']; const copyPhones = phones; copyPhones.push('Redmi'); console.log(phones); // ['Apple', 'Samsung', 'Nokia', 'OnePlus', 'Redmi']; console.log(copyPhones); // ['Apple', 'Samsung', 'Nokia', 'OnePlus', 'Redmi'];
So to overcome this problem, we need to deep copy objects and arrays.
Deep Copy
If we copy an object or array and all the level properties are copied without any references, then it is a Deep copy.
There are some methods (Object.assign(), spread operator and slice()) which can deep copy only the top level properties. That means these methods do not work for multi level objects or arrays.
Using Object.assign() for single level objects:
const phone = {model: 'Apple', version: 'iPhone X'}; const copyPhone = Object.assign({}, phone); console.log(copyPhone); // {model: 'Apple', version: 'iPhone X'};
Using spread operator (…) for single level objects:
const phone = {model: 'Apple', version: 'iPhone X'}; const copyPhone = {...phone}; console.log(copyPhone); // {model: 'Apple', version: 'iPhone X'}; //For Arrays const phones = ['Apple', 'Samsung', 'OnePlus']; const copyPhones = [...phones]; console.log(copyPhones); // ['Apple', 'Samsung', 'OnePlus'];
Using slice() method for Array:
const phones = ['Apple', 'Samsung', 'OnePlus']; const copyPhones = phones.slice(0); console.log(copyPhones); // ['Apple', 'Samsung', 'OnePlus'];
Object.assign() for multi level objects
const phone = { brand: 'Apple', storage: { ram: '8GB', memory: '128GB' } }; const copyPhone = Object.assign({}, phone); copyPhone.brand = 'Samsung'; // brand will be changed only for copy object copyPhone.storage.memory = '64GB'; // memory will be changed to 64 for both original and copy object console.log(phone); // {brand: 'Apple', storage:{ram: '8GB', memory: '64GB'}} console.log(copyPhone); // {brand: 'Samsung', storage:{ram: '8GB', memory: '64GB'}}
Let’s see how we can achieve deep cloning for multi level objects also in JavaScript.
Using recursive function:
To deep clone an object, you need to iterate through each property and check if the current property contains an object. If yes, then do a recursive call to the same function by passing the current property’s value (i.e. the nested object). Look at the below example.
const phone = { brand: 'Apple', storage: { ram: '8GB', memory: '128GB' } }; function makeDeepClone(phone) { let newObject = {}; Object.keys(phone).map(key => { if(typeof phone[key] === 'object'){ newObject[key] = makeDeepClone(phone[key]); } else { newObject[key] = phone[key]; } }); return newObject; } const copyPhone = makeDeepClone(phone); copyPhone.brand = 'Samsung'; copyPhone.storage.memory = '64GB'; console.log(phone); // {brand: 'Apple', storage:{ram: '8GB', memory: '128GB'}} console.log(copyPhone); // {brand: 'Samsung', storage:{ram: '8GB', memory: '64GB'}}
Using JSON.stringify() and JSON.parse():
First convert your original object into string and then parse it back to JSON object from it.
const phone = { brand: 'Apple', storage: { ram: '8GB', memory: '128GB' } }; const copyPhone = JSON.parse(JSON.stringify(phone)); copyPhone.brand = 'Samsung'; copyPhone.storage.memory = '64GB'; console.log(phone); // {brand: 'Apple', storage:{ram: '8GB', memory: '128GB'}} console.log(copyPhone); // {brand: 'Samsung', storage:{ram: '8GB', memory: '64GB'}}
This technique (
JSON.parse(JSON.stringify(obj))
) doesn’t work if your object property contains function as value. Because when you JSON.stringify the object, the property containing function as value gets removed from the object. So go for recursive function approach in such case.
You have learnt various ways to clone object and arrays in JavaScript. While cloning always check what type of object or array you are cloning, so carefully choose your cloning method by keeping the object structure in mind.
Reference
Difference between JSON.parse() and JSON.stringify()
Web Developer by Profession, Blogger by Passion.
JavaScript | React | Next | Angular | Vue | HTML | CSS