3 ways to clone an object in Javascript
Tags: beginners, webdev, javascript, tutorial
Published: 2021-05-17 08:38:10

Before proceeding, let me explain very briefly about Primitive and Reference types in Javascript. 
# Primitive and Reference type 
Javascript has 5 data types that can contain values. `Number`, `string`, `Boolean` , `null` and `undefined`. These are referred to as **primitive** data types. Basically these are passed by value.
Javascript has 3 data types that are passed by reference. `Object`,`Functions` and  `Arrays`. Technically,  these are all objects and called as **reference** data types
Primitive data types are immutable, which means their value cannot be modified once created.
Whereas, objects and arrays are mutable , meaning their value can be altered after creation.

##Consider the following examples.
*Let us start by copying/cloning a string* 
```javascript
let message1 = 'hello everyone'
let message2 = message1
message2 = 'hello world'

console.log(message1) // 'hello everyone' ✅
console.log(message2) // 'hello world' ✅
```
So for so good,, everything is working as expected .
*Let us implement the same logic for `object`*
```javascript
let myObj1 = {
  name : 'John Doe',
  age: 34
}

let myObj2 = myObj1
myObj2.name = 'Michael'

console.log(myObj1) //{name: 'Michael', age: 34} 😲 -> why does the original object `myObj2` got affected ?
console.log(myObj2) //{name: 'Michael', age: 34} ✅

```
🤔🤔
That's because objects are reference type(passed by reference). So, when you use '=', the pointer to the memory address of `myObj1` is copied to `myObj2`. Not the actual value is copied. Since, reference type don't hold values, they are pointer to the value in memory space.

## So,, how do you clone an object?
We can use variety of techniques such as the spread operator(...) or Object.assign() or with JSON.parse() and JSON.stringify().

###1. Using spread (...)
```javascript
let myObj1 = {
  name: 'John Doe',
  age: 34
}
let myObj2 = {...myObj1} 
myObj2.name = 'Michael'

console.log(myObj1) // {name: "John Doe", age: 34} ✅ Original object `myObj1` is not changed
console.log(myObj2) // {name: "Michael", age: 34} ✅
```
###2. Using Object.assign()
```javascript
let item1 = {
  pen: 23,
  pencil: 45
}

let item2 = Object.assign({}, item1)
item2.pen = 100
console.log(item1) // {pen: 23, pencil: 45} ✅ Original object `item1` is not changed
console.log(item2) // {pen: 100, pencil: 45} ✅
```
Note
> Both of the above techniques only does a shallow copy(only the outer part). If you want to perform a deep copy(nested part), there are a few approaches to this problem. The simple technique is by using our well known friend `JSON.parse()` and `JSON.stringify()`. But, it is not recommended to do deep copy using this technique, instead , you can use libraries such
as lodash, which is easy to implement and also robust.

###3. Using JSON (Not Recommended)
```javascript
let obj1 = {a:1,b:2,c:{d :3}}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.c.d = 45;

console.log(obj1) // {a: 1,b: 2,c: {d: 3}} ✅
console.log(obj2) // {a: 1,b: 2,c: {d: 45}} ✅
```
Note
> If you try to do the above example with spread or `Object.assign()`,it only modifies 
the outer part(shallow). 

For example,
```javascript
let obj = {a:1,b:2,c:{d :3}}
let shallowObj = {...obj}
shallowObj.b = 20
shallowObj.c.d = 30

console.log(shallowObj) //{a: 1,b: 20,c: {d: 30}} 😎
console.log(obj) //{a: 1,b: 2,c: {d: 30}}  🤯 -> Notice that only `b` value is not modified from the original `obj`, whereas, `d` value is modified
```
**A shallow copy means the first level is copied, deeper levels are referenced.**
This is where, shallow and deep copy plays an important role.

Thanks for reading my post 🙌🙌

##👉 Additional Resources
[MDN Web Docs:Object.assign()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
[MDN Web Docs:JSON.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)
[MDN Web Docs:JSON.stringify()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
[Shallow vs Deep Copy](https://medium.com/@manjuladube/understanding-deep-and-shallow-copy-in-javascript-13438bad941c)
[Primitive vs Reference Type](https://itnext.io/javascript-interview-prep-primitive-vs-reference-types-62eef165bec8)
[Why should you use lodash for deep copy](https://flaviocopes.com/how-to-clone-javascript-object/#:~:text=Lodash%20offers%20the%20very%20convenient,the%20size%20of%20the%20dependency.&text=In%20this%20simple%20example%20we,copy%2C%20and%20edit%20the%20i.)