Value vs Reference - JavaScript Concepts
Tags: javascript, beginners
Published: 2019-12-15 18:17:14

Before we go into JavaScript of things, let's look at what _Pass by Value_ and _Pass by Reference_ actually means.

Quoting [this](https://stackoverflow.com/a/430958/4374566) answer on stackoverflow,

- When a parameter is passed by reference, the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.

- When a parameter is passed by value, the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.

In essence, when you are passing a variable by reference, you are allowing a function to change the variable and hence bear the weight of side effects whatever that function did to your variable.

When passing by value, you give the function much lesser control. You will take into account only what is returned by the function. They can change the variables you pass in but that will not affect your variables.

But this concept is mostly outdated today. It is taught in colleges and for introductory classes but most modern languages choose to implement this way differently. Talking about modern languages, so does JavaScript.

JavaScript implements this concept with two types of data types: Primitives and Objects.

Instead of introducing two ways of passing variables to functions, we have two types of variables. The type of variable defines whether it is passed by value or by reference.

## Primitives

There are 6 primitive data types in JavaScript:

1. string
2. number
3. boolean
4. null
5. undefined
6. symbol

These data types are represented at the lowest level and are immutable.

Immutability means that their properties cannot be altered at run time. Like,

```javascript
let stringVar = 'this is one long string';
stringVar[4] = 'v'; // This is not possible
stringVar = 'this is another string'; // This is not barred by the datatype
```

### But I thought JavaScript did not have types

Yes, JavaScript is a loosely typed language. This still means that JavaScript has data types. But these data types are not bound to any variable.

```javascript
let variable = 'one';
variable = 1;
variable = true; // Totally fine executions
```

### How does this relate to Value vs Reference?

Primitives are always passed by value in the truest form.

```javascript
function crazy(data) {
  data = '_*.!@!!@(U!())'; // let this function do what it ever it wants, it wouldn't hurt out primitive
}

const impData = 'this is data as a string';
crazy(impData); // rest assured, impData (primitive) is safe from manipulation by crazy()
```

## Objects

Objects are the second kind of data type available in JavaScript.

> If you are wondering where are Arrays, Maps and all those wonderful things, they are all just objects with special methods underneath.

Let's define an object named `Person`:

```javascript
const person = {
  name: 'John',
};
```

This is how the structure would look in the memory.

![person pointing to object](https://thepracticaldev.s3.amazonaws.com/i/h2ljxy6it6tx87oqbfct.png)

As you can see, `{ name: 'John' }` is allocated a place in the memory and variable person is pointing to it.

Now, John has taken a role in life and is being reassigned.

```js
const person = {
  name: 'john',
};
const developer = person; // John has become a developer.
```

Let us look at the memory representaion for this change:

![developer and person variable pointing at the same object reference in memory](https://thepracticaldev.s3.amazonaws.com/i/gfra60hjp5mluxiquw3a.png)

Now, we have a second variable `developer` pointing at the same memory that `person` did.

So, let's say `developer` learns a new skill, he adds it to his skill array. And magically `person` variable would have learned this skill too. Because both these variables share the same object in memory.

```javascript
const person = {
  name: 'john',
  skills: ['hiking'],
};
const developer = person;
developer.skills.push('coding');
/* == comparison operator for objects just compares references */
console.log(person === developer); // true
```

What if a new person now joins the company and is also named 'John'?

```javascript
const person = {
  name: 'john',
  skills: ['hiking'],
}
const person2 = {
  name: 'john2',
  skills: ['hiking'],
}
person.skills.push('coding');
/* Should person2 learn coding just because he has the same portfolio as the other John? */
console.log(person === person2) \/\/ false, even though they share the same reference, they point at different memory instances and are obviously two different objects.

```

So, it is not the properties that matter, it is the memory it points to.

Everything that is an object (objects, arrays, functions, maps) are passed by reference in JavaScript. Going back to our earlier crazy example,

```javascript
function crazy(impData) {
  impData.data = '_*.!@!!@(U!())'; // your important data just got crazified
}

const impData = {
  data: 'suppper secret',
};
crazy(impData);
console.log(impData); // gone. changed to gibberish by crazy.
```

## How would I protect my objects from crazy functions?

### 1. Write lesser crazy functions. More Pure functions.

Pure functions are those that do not produce side effects. They interact only with their arguments and do not change them in anyway.

These functions produce result only as their return value.

```javascript
function sum(a, b) {  \/\/ Pure function
  return a+b;
}
function addValue(obj) {  \/\/ Impure function
  obj.value = 100;
}
```

But what if it is not your function? What if you are passing the object to a third party?

### 2. Spread it.

There is a ECMAScript Stage 4 proposal for using [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) for objects available [here](https://github.com/tc39/proposal-object-rest-spread). You can use it now with a [Babel Plugin](https://babeljs.io/docs/en/babel-plugin-proposal-object-rest-spread)

```javascript
function addValue(obj) {  \/\/ Impure function
  obj.value = 100;
}

const impObj = {
  value: 10,
}
addValue({...impObj});
```

What you have essentially done here is to create a _shallow_ copy of your `impObj`. Now the `addValue` can no longer hurt it by altering it's properties. You can think of it like deploying a replica.

There is also a less fancy way of doing this with [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)

But as you might have figured from the word _shallow_ there are issues with cloning like this.

```javascript
function doCrazy(obj) {  \/\/ Impure function
  obj.name = "Hehe";  \/\/No effect
  obj.skills.push("another");   \/\/ That seems to be breaking the illusion
}

const person = {
  name: 'John',
  skills: ['hiking']
}
doCrazy({...person});
console.log(person);
```

![person and personClone are still pointing to the same reference internally](https://thepracticaldev.s3.amazonaws.com/i/s4gmlustlmdjmfbq8tnb.png)

By building a shallow clone we have only eliminated the possibility of crazy people meddling with the first level of your object. The levels below it are still references and can be manipulated/changed by other functions/entities.

### 3. Deepclone it.

The next solution is to take the object clone it and go deeper and deeper into the object, find them clone them too.

> I don't know who you are, but if you are reference, I would clone you.

Luckily, there is a function to do that, [cloneDeep](https://lodash.com/docs/4.17.11#cloneDeep).

## Does this change the way I write code?

Well, it should. It should tell you why pure functions are so important in functional programming. It should tell you there are primitives and objects. and it should tell you how JavaScript implements Value vs Reference.

> Originally written on [my blog](https://blog.agney.dev/value-vs-reference/) Find me on [Twitter](https://twitter.com/agneymenon)