Value Types vs Reference types in JavaScript Explained
Tags: javascript, webdev, beginners, tutorial
Published: 2021-01-18 00:53:08

---
tags:
- javascript
- webdev
- beginners
- tutorial
published: true
title: Value Types vs Reference types in JavaScript Explained
cover_image: https://res.cloudinary.com/practicaldev/image/fetch/s--ohpJlve1--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://res.cloudinary.com/drquzbncy/image/upload/v1586605549/javascript_banner_sxve2l.jpg
---

When storing a variable in JavaScript, the JavaScript engine may store it as one of two types of values: a *primitive* or *reference* value. Understanding the difference in how they behave will help to avoid mistakes while manipulating them.

## An Example

Instead of jumping straight into a boring explaination, consider this script:

```
const firstList = ['A', 'B', 'C'];
const secondList = firstList;
secondList.push('D');
console.log('firstList:', firstList);
console.log('secondList:', secondList);
```
We may expect the output to be:
```
"firstList:" ['A', 'B', 'C'];
"secondList:" ['A', 'B', 'C', 'D'];
```
But instead, we get an output of:
```
"firstList:" ['A', 'B', 'C', 'D'];
"secondList:" ['A', 'B', 'C', 'D'];
```

## What Happened

This is because of how JavaScript treats arrays in memory. Arrays are stored as a *reference value*, so JavaScript will only copy the reference to that point in memory. This means that to the original array and not the value of the array.

Diving deeper, when accessing the varible as a primitive value, you are manipulating the actual value stored of that variable. In other words, the variable that is assigned a primitive value is accessed by value.

Unlike storing a primitive value, when you create an object, you are accessing the reference of that object in memory, rather than the actual value of that object. In other words, it means a variable that is assigned an object is accessed by reference.

## Fixing our Example

The **spread operator** will create a new *reference value* in memory.
```
const firstList = ['A', 'B', 'C'];
const secondList = [...firstList];
secondList.push('D');
console.log('firstList:', firstList); // "firstList:" ['A', 'B', 'C'];
console.log('secondList:', secondList); // "secondList:" ['A', 'B', 'C', 'D'];
```

In ES5, you could copy an array into a new *reference value* with the **slice** method.
```
const firstList = ['A', 'B', 'C'];
const secondList = firstList.slice();
secondList.push('D');
console.log('firstList:', firstList); // "firstList:" ['A', 'B', 'C'];
console.log('secondList:', secondList); // "secondList:" ['A', 'B', 'C', 'D'];
```

However, the **slice** method cannot be used to create **sparse arrays** or arrays with 'holes' in them.
```
let array = [];
array[2] = 2;
array[4] = 4;

console.log(array.slice()); // [empty × 2, 2, empty, 4]
console.log(...array); // undefined undefined 2 undefined 4

```

## Diving Deeper

Javascript has six data types that values are assigned as primative type: Boolean, null, undefined, String, Number, and Symbol. Like mentioned above, the values in primative types are accessed only by value, so they can be copied by value. The values can be copied and changed with no relation to each other.
```
let a = true;
let b = 'hello';
let x = a;
let y = b;
console.log(x, y, a, b); // true, 'hello', true, 'hello'
x = null;
y = undefined;
console.log(x, y, a, b); // null, undefined, true, 'hello'
```

Arrays, Functions, and Objects are all derived from object contructors in JavaScript. An explaination for this can be found [here](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch3.md). The important thing to understand is that objects are passed by *reference value*. Like mentioned above, a varible assigned an object only knows is the location of the object in memory, not the object itself. Here is an example of a common bug that occurs when working with objects: 

```
let vehicleOne = {
  seats: 2,
  airConditioning: true
};
let vehicleTwo = vehicleOne;
vehicleOne.color = 'red';
console.log(vehicleOne.color); // 'red'
console.log(vehicleTwo.color); // 'red'

vehicleTwo = {...vehicleOne};
vehicleOne.color = 'white';
console.log(vehicleOne.color); // 'white'
console.log(vehicleTwo.color); // 'red'
```
By using the '=' operator, we only assigned **vehicleTwo** the reference to the object, so any changes made to the **vehicleOne** object will alter the same spot in memory that **vehicleTwo** is assigned. Once again, we used the **spread operator** to copy and create a new *reference value* for **vehicleTwo** to avoid this error. This is why objects are known to be **mutable** in JavaScript. 

This is also why you need to treat state in React as immutable, because the *reference value* will not change if you try and manipulate the state directly. You can read more about treating state as being immutable in React [here](https://www.freecodecamp.org/news/handling-state-in-react-four-immutable-approaches-to-consider-d1f5c00249d5/).

## Deep Copying 

Both times we used the **spread operator**, it managed to create us a *reference value* for a new object. However, there is a catch. Consider this script: 

```
const bookOne = {
  title: 'Primative Types vs Reference Values in JavaScript',
  pages: 50,
  info: {
    name: 'Joseph',
    publication: 'dev.to'
  }
}

const bookTwo = { ...bookOne }


bookTwo.title = 'Immutability in JavaScript';
bookTwo.info.publication = 'medium.com';

console.log('Book One title:', bookOne.title); // 'Primative Types vs Reference Values in JavaScript'
console.log('Book One authors:', bookOne.info.publication); // 'dev.to'

console.log('Book Two:', bookTwo.title); // 'Immutability in JavaScript'
console.log('Book Two:', bookTwo.info.publication); // 'dev.to'
```

Only the title of **bookTwo** changed. If one of the elements is another *reference value* to another object, all it would do is make a copy of the *reference value* into memory and it will not change what it’s referenced to. [Here](https://blog.logrocket.com/methods-for-deep-cloning-objects-in-javascript/) is a great article for further reading into how to deep copy objects in JavaScript.