Understanding Different Ways of Object Cloning in Javascript

Object cloning in Javascript article banner

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)
Assignment operator output
Top-level/Direct Properties:- firstName and lastName

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 })

Object.assign() output
Note that Nested Property:- city of original object (member) has also changed.🙁

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 })
spread operator output (shallow copy)

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}}

spread operator output (Deep copy)

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.🙂

Latest

SENTRY integration in your React Native App for Error/Crash tracking

Sentry captures data by using an SDK within your...

Recall the concepts of useCallback.

useCallback hook is one of the best hooks offered...

Value of Comments in the code!!

During my journey of Software Development, I am always...

YOLO:Bullet Paced Algorithm

http://sh017.hostgator.tempwebhost.net/media/33949d0e61af4b50f374c534713f56b3 According to world health organization, more than 1.35 million...

Featured

Developing Enterprise Application in Node.js – CJS Vs ESM

Node.js is a popular runtime environment for building server-side...

Integrating your web react applications with their React Native(android and IOS) apps using QR code

Integrating a web application with Android and iOS apps...

YOLO: Bullet Paced Algorithm – popular choice for object detection in autonomous vehicles 

According to world health organization, more than 1.35 million...

JavaScript Objects

Introduction JavaScript is a versatile and flexible programming language, and one of its most powerful features is its ability to work with objects. Objects are...

Error Handling in React Js

Errors are bound to happen in our applications, whether they’re server-related errors, edge cases, api calling issues or others. As such, many methods have...

History of content updation in Strapi

Strapi is a Javascript-based, next-generation, open-source headless CMS. It provides developers the facility to use their favorite frameworks and tools to create, modify and...

LEAVE A REPLY

Please enter your comment!
Please enter your name here