Shallow Copy and Deep Copy in JavaScript...!
Have you ever tried copying an object or an array and not gotten the expected output? Let me explain the concept of copying in an easy way.
Shallow Copy and Deep Copy
When you are working with objects and arrays, you may need to make copies of them. Copying objects and arrays is not straightforward because JavaScript handles assignments and references. So we have Shallow Copy and Deep Copy.
Shallow Copy
In shallow copy first level of the object or array is copied, nested object or array is referenced.
if you make changes to the nested object or array, it will also affect the original object or array, as well as the copied object or array.
we have 2 methods to create a shallow copy in an object and an array
Object
- Spread Operator
- Object.assign()
Array
- Spread Operator
- Array.from()
let person = {
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: {
city: 'Bengaluru',
state: 'Karnataka',
country: 'Bharat'
}
};
//Printing original object
console.log(person);
/*
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'Bharat' }}
*/
//shallow copy using spread operator
let person1 = { ...person };
console.log(person1);
/*
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'Bharat' }}
*/
//let's change some value in the nested object through shallow copied object
person1.age = 27;
person1.address.country = 'India';
console.log(person1);
/*
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 27,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'India' }
}
*/
//you can see age didn't change in the original array because age is not a nested object but the country is changed because of nested object
console.log(person);
/*
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'India' }
}
*/
Deep Copy
In deep copy, all levels of the objects and arrays are copied. It creates a new object or array with new memory locations for all of its properties and nested objects or arrays.
So if you make changes to the copied Object or Array or any of its nested objects or arrays, it will not affect the original object or array.
A deep copy can be achieved using JSON.parse() + JSON.stringify()
let person = {
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: {
city: 'Bengaluru',
state: 'Karnataka',
country: 'Bharat'
}
};
console.log(person);
/*
original object
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'Bharat' }
}
*/
//deep copy using JSON.parse() + JSON.stringify()
let person1 = JSON.parse(JSON.stringify(person));
console.log(person1);
/*
deep copied object
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'Bharat' }
}
*/
// Modify the copied object without affecting the original
person1.age = 27;
person1.address.country = 'India';
console.log(person1);
/*
deep copied object after changes
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 27,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'India' }
}
*/
//No value is changed in an original object because of deep copy
console.log(person);
/*
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'Bharat' }
}
*/
JSON.parse() + JSON.stringify() has some downsides. It ignores function properties and ignores properties whose value is undefined. To overcome this we can use the library called lodash.
You can install it using npm or yarn
npm install lodash
# or
yarn add lodash
const _ = require('lodash');
let person = {
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: {
city: 'Bengaluru',
state: 'Karnataka',
country: 'India'
},
hobbies: ['reading', 'swimming'],
};
console.log(person);
/*
printing original object
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'India' },
hobbies: [ 'reading', 'swimming' ]
}
*/
// Deep copy the object using _.cloneDeep()
let person1 = _.cloneDeep(person);
console.log(person1);
/*
printing after deep copy
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'India' },
hobbies: [ 'reading', 'swimming' ]
}
*/
// Modify the copied object without affecting the original
person1.age = 27;
person1.address.country = 'Bharat';
person1.hobbies[1] = 'Cooking';
console.log(person1);
/*
printing after modifying
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 27,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'Bharat' }
,
hobbies: [ 'reading', 'Cooking' ]
}
*/
console.log(person);
/*
checking whether original object changed or not
{
firstName: 'K',
lastName: 'Subramanyeshwara',
age: 28,
address: { city: 'Bengaluru', state: 'Karnataka', country: 'India' },
hobbies: [ 'reading', 'swimming' ]
}
*/
Conclusion
shallow copies are a lot faster than deep copies. So, which option should I use?
- If the depth of your object is equal to one, use a shallow copy.
- If the depth of your object is bigger than one, use a deep copy.
Thank you for taking the time to read this article ๐. I hope the article provided you with valuable insights. I would highly appreciate it if you take a moment to like ๐, share your thoughts or feedback comment โ๏ธ, and share ๐ it.
Happy Learning...! โ๏ธโ๏ธโ๏ธ