Functional Programming Concepts in JavaScript
Tags: javascript, webdev, programming, functional
Published: 2021-01-25 01:28:44

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Functional programming is a programming paradigm which states that we create computation as the evaluation of functions and avoid changing state and mutable data.

In JavaScript, we can apply these principles to make our programs more robust and create fewer bugs.

In this article, we’ll look at how to apple some functional programming principles in our JavaScript programs, including pure functions and creating immutable objects.

### Pure Functions

Pure functions are functions that always return the same output given the same set of inputs.

We should use pure functions as much as possible because they’re easier to test and the output is always predictable given a set of inputs.

Also, pure functions don’t create any side effects, which means that it does change anything outside the function.

An example of a pure function would be the following `add` function:

```
const add = (a, b) => a + b;
```

This function is a pure function because if we pass in 2 numbers, we’ll get the 2 numbers added together returned.

It doesn’t do anything outside the function, and it doesn’t have values that change the returned value inside the function.

Example of functions that aren’t pure functions include:

```
let x;
const setX = val => x = val;
```

`setX` isn’t a pure function because it sets the value of `x` which is outside the function. This is called a side effect.

A side effect is a state change that’s observed outside the called function other than its returned value. `setX` sets a state outside the function, so it commits a side effect.

Another example would be the following:

```
const getCurrentDatePlusMs = (milliseconds) => +new Date() + milliseconds;
```

`getCurrentDatePlusMs` returns a value that depends on `+new Date()` which always changes, so we can check the value of it with tests easily. It’s also hard to predict the return value given the input since it always changes.

`getCurrentDatePlusMs` isn’t a pure function and it’s also a pain to maintain and test because of its ever-changing return value.

To make it pure, we should put the `Date` object outside as follows:

```
const getCurrentDatePlusMs = (date, milliseconds) => +date + milliseconds;
```

That way, given the same date and milliseconds, we’ll always get the same results.

### Immutability

Immutability means that a piece of data can’t be changed once it’s defined.

In JavaScript, primitive values are immutable, this includes numbers, booleans, strings, etc.

However, there’s no way to define an immutable object in JavaScript. This means that we have to be careful with them.

We have the `const` keyword, which should create a constant by judging from the name of it, but it doesn’t. We can’t reassign new values to it, and we can’t redefine a constant with the same name.

However, the object assigned to `const` is still mutable. We can change its properties’ values, and we can remove existing properties. Array values can be added or removed.

This means that we need some other way to make objects immutable.

Fortunately, JavaScript has the `Object.freeze` method to make objects immutable. It prevents property descriptors of an object from being modified. Also, it prevents properties from being deleted with the `delete` keyword.

Once an object is frozen, it can’t be undone. To make it mutable again, we have to copy the object to another variable.

It applies these changes to the top level of an object. So if our object has nesting, then it won’t be applied to the nested objects.

We can define a simple recursive function to do freeze level of an object:

```
const deepFreeze = (obj) => {
  for (let prop of Object.keys(obj)) {
    if (typeof obj[prop] === 'object') {
      Object.freeze(obj[prop]);
      deepFreeze(obj[prop]);
    }
  }
}
```

The function above goes through every level of an object and calls `Object.freeze` on it. This means it makes the whole nested object immutable.

We can also make a copy of an object before manipulating it. To do this, we can use the spread operator, which works with objects since ES2018.

For example, we can write the following function to make a deep copy of an object:

```
const deepCopy = (obj, copiedObj) => {
  if (!copiedObj) {
    copiedObj = {};
  }

  for (let prop of Object.keys(obj)) {
    copiedObj = {
      ...copiedObj,
      ...obj
    };
    if (typeof obj[prop] === 'object' && !copiedObj[prop]) {
      copiedObj = {
        ...copiedObj,
        ...obj[prop]
      };
      deepCopy(obj[prop], copiedObj);
    }
  }
  return copiedObj;
}
```

In the code above, we create a new `copiedObj` object to hold the properties of the copied object if it doesn’t exist yet, which shouldn’t in the first call.

Then we loop through each property of the `obj` object and then apply the spread operator to `copiedObj` and `obj` to make a copy of the values at a given level. Then we do this recursively at every level until we went through every level, then we return the final `copiedObj` .

We only apply the spread operator if the property doesn’t exist at that level yet.

How do we know that this works? First, we can check if properties of each value are the same, which it is if we run `console.log` on it. Then we can also check with the `===` if the copied object has the same reference as the original object.

For example, if we have:

```
const obj = {
  foo: {
    bar: {
      bar: 1
    },
    a: 2
  }
};
```

Then we can check by writing:

```
const result = deepCopy(obj);
console.log(result);
```

To check the content of `result` .

We should get:

```
{
  "foo": {
    "bar": {
      "bar": 1
    },
    "a": 2
  }
}
```

This is the same as `obj` . If we run:

```
console.log(result === obj);
```

we get `false` , which means the 2 aren’t referencing the same object. This means that they’re a copy of each other.

Pure functions and immutability are important parts of functional programming. These concepts are popular for a reason. They make outputs predictable and make accidental state changes harder.

Pure functions are predictable since they return the same output for the same set of inputs.

Immutable objects are good because it prevents accidental changes. Primitive values in JavaScript are immutable, but objects are not. We can freeze it with the `Object.freeze` method to prevent changes to it and we can also make a copy of it recursively with the spread operator.