In this article we will understand the Different ways for Cloning Objects that Javascript offers to us, but first, we need to understand what Shallow and Deep copy are.
In Deep copy, all the properties of an original object are copied into a new object, which is now completely disconnected from the original object. So changes made in a new object don’t have an effect on the original object.
But In Shallow copy, direct properties or sub-properties/nested properties are still connected to the original object, so changes made in the new object will have an effect on the original object.
NOTE :- FOR PRIMITIVE DATA TYPES LIKE NUMBER, BOOLEAN, STRING, NULL, UNDEFINED , JAVASCRIPT DOES DEEP COPY BY DEFAULT. FOR NON-PRIMITIVE DATA TYPES LIKE OBJECT, ARRAY, FUNCTIONS, SET, ETC., JAVASCRIPT DOES SHALLOW COPY.
Okay, Now we know what Shallow and Deep copy are… Yay! 🥳, So let’s see the different ways that Javascript offers for cloning objects.
1. Assignment Operator
An assignment operator is used to assign values to JavaScript variables.
const member = { 'firstName': 'Aniket', 'lastName': 'Kapoor', } const stranger = member stranger.firstName = 'Aryan' console.log('member (original Object) ::',member) console.log('stranger (cloned Object) ::',stranger)
As you notice, changes made in the cloned object (stranger) also changed the property of an original object (member). The assignment operator (=) did a shallow copy because both made reference to the same object in memory.
2. Object.assign(target , …source)
- Target: object to which properties are copied.
- Source: object from which properties are copied.
const member = { 'firstName': 'Aniket', 'lastName': 'Kapoor', 'address': { 'city': 'New Delhi', 'pin': 110006 } } const stranger = Object.assign({},member) stranger.firstName = 'Aryan' stranger.address.city = 'Noida' console.log('--- member object ---') console.log({FirstName: member.firstName , City : member.address.city }) console.log('--- stranger object ---') console.log({FirstName: stranger.firstName , City : stranger.address.city })
This method copies the direct properties of objects and doesn’t have an effect on the original object. However, in the case of nested properties, changes made in the cloned object change the nested properties of the original object, which means the object.assign() performs shallow copy.
3. hasOwnProperty()
This method is used by iterating through a source object’s properties and copying them one after the other to a target object. But this only works for direct properties and not for nested properties.
const member = { 'firstName': 'Aniket', 'lastName': 'Kapoor', 'address': { 'city': 'New Delhi', 'pin': 110006 } } let stranger = {} for (let key in member) { if (member.hasOwnProperty(key)) { stranger[key] = member[key] } } stranger.firstName = 'Aryan' stranger.address.city = 'Noida' console.log('--- member object ---') console.log({FirstName: member.firstName , City : member.address.city }) console.log('--- stranger object ---') console.log({FirstName: stranger.firstName , City : stranger.address.city })
4. Spread operator
Spread operator or three dots (…) introduced in ES6. This is also one method for copying / cloning objects.
const member = { 'firstName': 'Aniket', 'lastName': 'Kapoor', 'address': { 'city': 'New Delhi', 'pin': 110006 } } const stranger = {...member} stranger.firstName = 'Aryan' stranger.address.city = 'Noida' console.log('--- member object ---') console.log({FirstName: member.firstName , City : member.address.city }) console.log('--- stranger object ---') console.log({FirstName: stranger.firstName , City : stranger.address.city })
As you can see, the Spread Operator modifies the original object’s nested property (city) also 🙁, implying that the spread operator performs shallow copy. But (with some additional code) we can also achieve deep copy by using the spread operator for nested objects.😁
const stranger = {...member, address:{...member.address}}
5. JSON.stringify() & JSON.parse()
- JSON.stringify() method takes in an object and converts it into a JSON string.
- JSON.parse() method takes in a String and converts it into a JavaScript object.
By combining both, we can create a copy of an object, and the best part is that it works both for direct and nested properties.😃
const member = { 'firstName': 'Aniket', 'lastName': 'Kapoor', 'address': { 'city': 'New Delhi', 'pin': 110006 } } const stranger = JSON.parse((JSON.stringify(member))) stranger.firstName = 'Aryan' stranger.address.city = 'Noida' console.log('--- member object ---') console.log({FirstName: member.firstName , City : member.address.city }) console.log('--- stranger object ---') console.log({FirstName: stranger.firstName , City : stranger.address.city })
6. structuredClone()
This method is also used for object cloning and works for both direct and nested properties.
const member = { 'firstName': 'Aniket', 'lastName': 'Kapoor', 'address': { 'city': 'New Delhi', 'pin': 110006 } } const stranger = structuredClone(member) stranger.firstName = 'Aryan' stranger.address.city = 'Noida' console.log('--- member object ---') console.log({FirstName: member.firstName , City : member.address.city }) console.log('--- stranger object ---') console.log({FirstName: stranger.firstName , City : stranger.address.city })
Summary
There are still many other ways for cloning objects, we can also perform object cloning using the external dependency library Lodash which has object Cloning utility methods like _.clone() and _.cloneDeep().
So to conclude, Javascript offers us many ways for object cloning, each with its pros and cons, and according to our requirements, we need to choose one.😄
Thanks For Reading, I hope you found this Article helpful.🙂