Value VS Reference in Javascript
Tags: javascript, programming
Published: 2021-01-19 20:36:59

---
title: Value VS Reference in Javascript
published: true
description: 
tags: javascript, programming
cover_image: https://images.unsplash.com/photo-1611065695758-ff2103833f2a?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80
---

# Overview
* Javascript has 6 primitive data types: [`string`](https://developer.mozilla.org/en-US/docs/Glossary/string), [`number`](https://developer.mozilla.org/en-US/docs/Glossary/number), [`bigint`](https://developer.mozilla.org/en-US/docs/Glossary/bigint), [`boolean`](https://developer.mozilla.org/en-US/docs/Glossary/boolean), [`undefined`](https://developer.mozilla.org/en-US/docs/Glossary/undefined), [`symbol`](https://developer.mozilla.org/en-US/docs/Glossary/symbol). Although [`null`](https://developer.mozilla.org/en-US/docs/Glossary/null) is also considered as a primitive data type because of it's behavior, But in certain cases, `null` is not as "primitive" as it first seems! since every object is derived from `null` by the [`Prototypal Chain`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance) and therefore `typeof` operator returns object for it.

* **The primitive data types are copied by value.**

* Javascript also provides another data structure like `Object`, which itself is used for creating other non-primitive data-types like `Array`, `Function`, `Map`, `Set`, `WeakMap`, `WeakSet`, `Date`.

* **These non-primitive data types are copied by reference.**

### Primitive Data Types Examples
Let's take the examples of copying primitive data types.
Here we can see that the values are copied as it is to other variables.
```javascript
let a1 = "Javascript";
let b1 = 10;
let a2 = a1;
let b2 = b1;
console.log(a1, b1, a2, b2); 
// Javascript 10 Javascript 10
```

Now, if we assign something else to the previously declared `a2` and `b2` variables, we can see that the value stored inside `a1` and `b1` didn't get impacted.
```javascript
let a1 = "Javascript";
let b1 = 10;

let a2 = a1;
let b2 = b1;

a2 = "Java";
b2 = 20;
console.log(a1, b1, a2, b2); 
// Javascript 10 Java 20
```   

### Non-Primitive Data Types Examples
Now suppose we've a non-primitive data type and we copy it to another variable.
```javascript
let arr1 = ["1", "2", "3", "4"];
let arr2 = arr1;
console.log(arr1, arr2); 
// ["1", "2", "3", "4"]
// ["1", "2", "3", "4"]
```  

But now if we make some change to arr2.
```javascript
arr2[2] = "5";
console.log(arr1, arr2);
// ["1", "2", "5", "4"]
// ["1", "2", "5", "4"]
```
We can see that the change made to the copied array `arr2` also reflects in the original array `arr1`. So what happens when we did `arr2 = arr1` was, we assigned the reference of the value stored inside arr1 to arr2. And this is the case with all non-primitive data types.

<br>

So what can be done if suppose we want to copy a non-primitive data type, say array for example.
```javascript
let arr = ["1", "2", "3", "4"];
// Option-1: Using Array.prototype.slice() method. [Shallow Copy]
let arrCopy1 = arr.slice();
// Option-2: Using Array.prototype.concat() method. [Shallow Copy]
let arrCopy2 = [].concat(arr);
// Option-3: Using es6 spread operator. [Shallow Copy]
let arrCopy3 = [...arr];
// Option-4: Using Array.from() method [Shallow Copy]
let arrCopy4 = Array.from(arr);
```
So now if we change anything inside these new copied arrays, the original values inside `arr` won't change.
For shallow copying of `Objects` use Object.assign()
```javascript
let car = {"brand": "BMW", "wheels": 4};
let bike = Object.assign({}, car, {"wheels":2, "safety":3});
console.log(car, bike);
// {brand: "BMW", wheels: 4} {brand: "BMW", wheels: 2, safety: 3}
```

### Shallow VS Deep Copy (Array)
But a thing to remember here is that all these techniques perform `shallow copy` instead of a `deep copy`, i.e. If the array is nested or multi-dimensional or contains objects, and if we change anything inside those it won't work.
Let me explain with an example:
Here I'm taking `Array.prototype.slice()` for copying but any of the others can also be used.
```javascript
let obj1 = {"name":"shivaansh"};
let obj2 = {"name":"agarwal"};
let arr = [obj1, obj2];
let arrCopy1 = arr.slice();
arrCopy1[0].age = 22;
console.log(arr, arrCopy1);
/*
[{"name":"shivaansh", "age":22}, {"name":"agarwal"}]
[{"name":"shivaansh", "age":22}, {"name":"agarwal"}]
*/
```
As we can see here in case of deep copy the above technique fails.

So to avoid this some developers usually prefer using the JSON methods.
```javascript
let obj1 = {"name":"shivaansh"};
let obj2 = {"name":"agarwal"};
let arr = [obj1, obj2];
let arrCopy1 = JSON.parse(JSON.stringify(arr));
arrCopy1[0].age = 22;
console.log(arr, arrCopy1);
/*
[{"name":"shivaansh"}, {"name":"agarwal"}]
[{"name":"shivaansh", "age":22}, {"name":"agarwal"}]
*/
```
<br>
But as pointed out by [Samantha Ming](https://dev.to/samanthaming) in her [blog](https://dev.to/samanthaming/how-to-deep-clone-an-array-in-javascript-3cig), even `JSON` technique might fail as it'll not work with values not compatible with `JSON` like suppose if we've a function being assigned to an object property inside an array.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vkjs9uqcbm1jsifgoq81.PNG)

Also, consider the following example,
```javascript
function nestedCopy(array) {
    return JSON.parse(JSON.stringify(array));
}

// undefined are converted to nulls
nestedCopy([1, undefined, 2]) // -> [1, null, 2]

// DOM nodes are converted to empty objects
nestedCopy([document.body, document.querySelector('p')]) // -> [{}, {}]

// JS dates are converted to strings
nestedCopy([new Date()]) // -> ["2019-03-04T10:09:00.419Z"]
```

### deepClone by lodash or custom function
* **JSON.stringify/parse** only work with Number and String and Object literal without function or Symbol properties.
* **deepClone** works with all types, function and Symbol are copied by reference.

#### Example of Lodash Solution by [Alfredo Salzillo](https://dev.to/alfredosalzillo),
```javascript
const lodashClonedeep = require("lodash.clonedeep");

const arrOfFunction = [() => 2, {
    test: () => 3,
}, Symbol('4')];

// deepClone copy by refence function and Symbol
console.log(lodashClonedeep(arrOfFunction));
// JSON replace function with null and function in object with undefined
console.log(JSON.parse(JSON.stringify(arrOfFunction)));

// function and symbol are copied by reference in deepClone
console.log(lodashClonedeep(arrOfFunction)[0] === lodashClonedeep(arrOfFunction)[0]);
console.log(lodashClonedeep(arrOfFunction)[2] === lodashClonedeep(arrOfFunction)[2]);
```

#### Example of Recursive function Solution by [Tareq Al-Zubaidi](https://medium.com/@zubaidi/there-is-other-simple-and-more-performant-solution-for-this-problem-8c8bda77d042)
```javascript
const clone = (items) => items.map(item => Array.isArray(item) ? clone(item) : item);
```

# References:
1. https://www.educative.io/courses/step-up-your-js-a-comprehensive-guide-to-intermediate-javascript/7nAZrnYW9rG
2. https://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value
3. https://www.freecodecamp.org/news/understanding-by-reference-vs-by-value-d49139beb1c4/
4. https://javascript.info/object-copy
5. https://dev.to/samanthaming/how-to-deep-clone-an-array-in-javascript-3cig
6. Javascript30 Course by WesBros