Proper Ways to Clone an Object in JavaScript
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']
};
Copying 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 propertycar2.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' },
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' },😂
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 passed 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' },
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' },
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' },
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' } }
Printing both objects we can see that the deep copy newPost
have copied properly the title
, tags
and author
but date
is converted to a 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.