ES6: How to Clone an Object in javascript ?
Tags: javascript, beginners, programming, tutorial
Published: 2022-01-19 21:03:34

Hey Folks👋 hope you doing well.
So you must be thinking, "Clone an Object"??? whats the big deal?
Well, i also think this way until i encounter an issue which took me 2 days just to debug that i have done something terrible with cloning an object.

So lets see how can we clone objects in javascript

```
// we have a user object
const user = {
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com"
} 
```
Now, if we want to copy this user object, so? simple!

```
const copiedUser = user;
```
Easy right?... well thats the worst way of copying a user,it is clear that you have some misconceptions of what the statement `const copiedUser = user;` does.

In JavaScript objects are passed and assigned by reference (more accurately the value of a reference), so `user` and `copiedUser` are both references to the same object.

```
// [Object1]<--------- user

const copiedUser = user;

// [Object1]<--------- user
//         ^ 
//         |
//         ----------- copiedUser
```
As you can see after the assignment, both references are pointing to the same object.

```
const user = {
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com"
}  
const copiedUser = user;
copiedUser.name = "XYZ"
console.log(copiedUser) // {name:"XYZ",email:"st.deepak15@gmail.com"}
console.log(user) // {name:"XYZ",email:"st.deepak15@gmail.com"}
```
modifing any of them will change both of them :(

So then how we can create copy if we need to modify one and not the other?

**1. Spread Operator**

```
const spreadUser = {...user}
spreadUser.name = "XYZ"
console.log(spreadUser) // {name:"XYZ",email:"st.deepak15@gmail.com"}
console.log(user) // {name:"Deepak Negi",email:"st.deepak15@gmail.com"}

```

**2. Object.assign()**
```
const assignUser = Object.assign({}, user);
assignUser.name = "XYZ"
console.log(assignUser) // {name:"XYZ",email:"st.deepak15@gmail.com"}
console.log(user) // {name:"Deepak Negi",email:"st.deepak15@gmail.com"}

```
Yaassss we finally got it!

<img width="100%" style="width:100%" src="https://tenor.com/view/confetti-party-yay-sexy-celebrate-gif-5509359">

If you think thats it.. so no... there much more to know, now we have added some more data in the user object and now lets see what happen.

```
const user = {
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"New Delhi",
    state:"Delhi",
    zipcode: 000000,
    country:"India"
  }
}
const spreadUser = {...user}
spreadUser.address.city = "Pune"
spreadUser.address.state = "Mumbai"

console.log(spreadUser)
// console output 
{
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"Pune",
    state:"Mumbai",
    zipcode: 000000,
    country:"India"
  }
}

console.log(user)
// console output 
{
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"Pune",
    state:"Mumbai",
    zipcode: 000000,
    country:"India"
  }
}
```
You see the problem, our actual user object is also changed now and this happens with `Object.assign()` method as well.

But why?
Because of the **shallow copying** i.e. object spread operator, as well as Object.assign, does not clone the values of nested objects, but copies the reference to the nested object. That's called **shallow copying**.

Then what should we do? Deep copy?
Yes, Deep copy/Deep clone will copies object, even nested properties, to do so serialize the object to JSON and parse it back to a JS object.

```
const user = {
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"New Delhi",
    state:"Delhi",
    zipcode: 000000,
    country:"India"
  }
}
const deepCopiedUser = JSON.parse(JSON.stringify(user))

deepCopiedUser.address.city = "Pune"
deepCopiedUser.address.state = "Mumbai"

console.log(deepCopiedUser)
// console output 
{
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"Pune",
    state:"Mumbai",
    zipcode: 000000,
    country:"India"
  }
}

console.log(user)
// console output 
{
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"New Delhi",
    state:"Delhi",
    zipcode: 000000,
    country:"India"
  }
}

```
So now our original `user` object doesn't change when we modify the `deepCopiedUser`.

> Beware using the `JSON.parse(JSON.stringify(user))` if you're dealing with date, functions, RegExps, Maps, Sets or other complex types within your object. The JSON method can't handle these types.

So for such cases the [**lodash clonedeep**](https://lodash.com/docs/4.17.15#cloneDeep) method is probably the best way to go.

```
import {cloneDeep} from 'lodash'
or
const {cloneDeep} = require('lodash')

const user = {
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"New Delhi",
    state:"Delhi",
    zipcode: 000000,
    country:"India"
  }
}
const deepCloneUser = cloneDeep(user)
deepCloneUser.address.city = "Pune"
deepCloneUser.address.state = "Mumbai"

console.log(deepCloneUser)
// console output 
{
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"Pune",
    state:"Mumbai",
    zipcode: 000000,
    country:"India"
  }
}

console.log(user)
// console output 
{
  name:"Deepak Negi",
  email:"st.deepak15@gmail.com",
  address:{
    line1:"ABC, Tower X",
    city:"New Delhi",
    state:"Delhi",
    zipcode: 000000,
    country:"India"
  }
}
```
Finally!!
<img width="100%" style="width:100%" src="https://tenor.com/view/done-well-gif-18074129">

Let me know in the comment what do you think the best way for deep cloning the object.