Objects in JavaScript are reference values and can store complex key-value properties.
let story = {
title: 'Proper Ways to Copy(Clone) an Object in JavaScript',
author:{
name:'pkoulianos',
email:'petran@pkoulianos.com'
},
tags:['Javascript','programming']
};
Copy an object can be a little tricky. But donโt worry about in this story weโll cover how to copy an object in proper ways.
1. The Fatal๐ก Way to Copy an Object
A fatal way to try copying an object is to use the assign = operator. The reason is that the assign operator will only pass the reference to the new variable.
Letโs see a simple example
let car1 = { color:โwhiteโ, type:โ4X4'};// fatal way to copy an object
let car2 = car1;//change the color property
car2.color = โredโ;console.log(car1);
**//{ color: 'red', type: '4X4' }** ๐๐
console.log(car2);
**//{ color: 'red', type: '4X4' }** ๐๐
In the above example, we create a new object car1 and try to copy it with the = operator to a new variable car2 and we change the color property. Printing both objects we can see that is identical and the reason is that both car1 and car2 have the same reference of the object.
2. Get a Shallow๐ง copy
Shallow copy will copy all enumerable own properties from the source object to the target.
In simple terms, a shallow copy will not truly copy :
- Arrays, Sets, etc
- Inner objects
Get a shallow copy with Object.assign()
Object.assign() will get you a shallow copy of your target object:
let post = {
title:'How to copy objects in JS',
tags:['js','js-basics','programming'],
date: new Date(),
author:{
name:'petros',
email:'petran@pkoulianos.com'
},
getAuthorData: function(){
return this.author.name+'-'+this.author.email;
}
};let newPost = Object.assign({},post);
newPost.title = 'I love js'
newPost.tags[0] = 'web-programming'
newPost.author.name = 'Petran';
newPost.date = new Date(1970);console.log(post);
console.log(newPost);//console output
{ title: 'How to copy objects in JS',
tags: ['web-programming', 'js-basics', 'programming'],
date: 2020-07-21T18:48:29.112Z,
author: { name: 'Petran', email: '[petran@pkoulianos.com](mailto:petran@pkoulianos.com)' },
getAuthorData: [Function: getAuthorData] }
{ title: 'I love js',๐
tags: ['web-programming', 'js-basics', 'programming'],๐
date: 1970-01-01T00:00:01.970Z,๐
author: { name: 'Petran', email: '[petran@pkoulianos.com](mailto:petran@pkoulianos.com)' },๐
getAuthorData: [Function: getAuthorData] }๐
In the above example, we create a new object post and copy it with Object.assign() to a new variable newPost and we change all properties. Printing both objects we can see that the shallow copy newPost have copied properly the title ,date and getAuthorData but tags and author are pass by reference.
Get a shallow copy with โฆSpread operator
The spread operator will get you also a shallow copy of your target object:
/ \*\*\* /
**let newPost = {...post}**
/ \*\*\* /
console.log(post);
console.log(newPost);//console output
{ title: 'How to copy objects in JS',
tags: ['web-programming', 'js-basics', 'programming'],
date: 2020-07-21T18:48:29.112Z,
author: { name: 'Petran', email: '[petran@pkoulianos.com](mailto:petran@pkoulianos.com)' },
getAuthorData: [Function: getAuthorData] }
{ title: 'I love js',
tags: ['web-programming', 'js-basics', 'programming'],
date: 1970-01-01T00:00:01.970Z,
author: { name: 'Petran', email: '[petran@pkoulianos.com](mailto:petran@pkoulianos.com)' },
getAuthorData: [Function: getAuthorData] }
3. Get a Deep๐ copy
A deep copy of an object will solve the mystery of getting a proper copy of inner objects and arrays, sets, etc but date objects will be converted to string and functions will not be copied at all.
We can get a deep copy by using the JSON object.
let targetObj = JSON.parse(JSON.stringify(sourceObj));
/ \*\*\* /
let newPost = JSON.parse(JSON.stringify(post));
/ \*\*\* /
console.log(post);
console.log(newPost);//console output
{ title: 'How to copy objects in JS',
tags: ['js', 'js-basics', 'programming'],
date: 2020-07-21T18:54:35.964Z,
author: { name: 'petros', email: '[petran@pkoulianos.com](mailto:petran@pkoulianos.com)' },
getAuthorData: [Function: getAuthorData] }
{ title: 'I love js',
tags: ['web-programming', 'js-basics', 'programming'],
date: **'2020-07-21T18:54:35.964Z'** ,๐
author: { name: 'Petran', email: '[petran@pkoulianos.com](mailto:petran@pkoulianos.com)' } }
Printing both objects we can see that the deep copy newPost have copied properly the title , tags and author but date is converted to string and getAuthorData are not copied at all.
5. Conclusion
Both Shallow and Deep copies have their own pros and cons. Before we decide which copy is right, we have to be sure about the object properties.
Top comments (1)
When I was a beginner some years ago, I would've loved to have read such a clear written explanation. I used to get many errors related to shallow copies.