Pure Functions in JavaScript

ยท

4 min read

Featured on daily.dev
Pure Functions in JavaScript

Functional programming is a programming paradigm that's been gaining a lot of traction in JavaScript. One of the core concepts of functional programming is pure functions and writing declarative vs. imperative code. In this article, I'll define what pure functions are, why they're beneficial, and how to construct them.

What are Pure Functions?

Pure functions consist of the following two concepts:

  1. Given the same inputs, the function will always return the same output.
    • The function is not dependent on any mutable data or variables that are declared outside of its scope. You'll sometimes see the term referential transparency used when describing this concept.
  2. No side effects. ๐Ÿšซ
    • The function should not modify anything outside of its scope. (I'll provide a non-exhaustive list of side effects later on in the article.)

The main gist is that pure functions typically accept parameters and, if they perform an action on said parameters, they do NOT directly mutate data. Instead, it creates a copy or new version of the data that it is referencing and operates off of that.

Side Effects

As the name implies, side effects are actions that happen as a result of a function being invoked. In order for a function to be considered "pure", it cannot cause any side effects.

Here's a non-exhaustive list of things that can produce side-effects:

  1. console.log()
  2. Making API calls
  3. State changes
  4. DOM manipulation
  5. Math.random()
  6. Attaching event listeners
  7. Modifying variables outside the scope of the function.
    • This includes methods that modify arrays like pop() or push() or adding properties to objects. To avoid this, it's best practice to create a copy of the array or object coming in and then modify the copy.

Benefits of Pure Functions

One of the biggest benefits of pure functions is their predictability. Because we know that given the same input we will always produce the same output and that there will be no side effects, the developer can trust that this function is reliable to use. Since pure functions are modular little pieces of code that can be ported around it makes them very composable and also makes them easier to test and it can help in mitigating bugs.

Pure vs. Impure Functions

The best way to demonstrate the differences between an impure and pure function is through an example so let's take a look at some code.

const numbers = [1, 2, 3, 4, 5]

//Impure Example
function removeLastItemImpure(){
  numbers.pop()
  return numbers
}

There are a few "pure rules" that are being broken:

  1. removeLastItemImpure accepts no arguments and performs its operations on the numbers variable that is defined outside the scope of the function.
  2. The function uses the pop() method which directly modifies (mutates) the array.

Now let's take a look at how we can achieve the same result with a pure function:

const numbers = [1, 2, 3, 4, 5]

//Pure Example
function removeLastItemPure(arr) {
  return arr.slice(0, arr.length - 1)
}
  1. The function accepts an argument, arr, that it can work with so that we are no longer referencing variables outside the function's scope.
  2. Instead of using the pop() method which directly modifies an array, we leverage the slice() method which returns a shallow copy of a new array containing the extracted elements.

Can Every Function be Pure?

The plain and simple answer is "no." For an application to be interactive and do useful things, there needs to be some form of state. Customers fill out forms, a computer game takes you to different levels based on checkpoints, the DOM needs to change to display different things, etc. A website or application without any side effects would be pretty boring.

Side effects and impure functions are not necessarily bad. In fact, it's darn near impossible to create a useful application that doesn't have some form of side effects. However, the goal should be to isolate these side effects to a certain location in your code so that you know when to expect particular outcomes.

El Fin ๐Ÿ‘‹๐Ÿฝ

Composing pure functions together is a big part of functional programming and can provide a lot of benefits to a codebase.

If you enjoy what you read, feel free to like this article or subscribe to my newsletter, where I write about programming and productivity tips.

As always, thank you for reading, and happy coding!

Resources