How to Avoid Side Effects with Pure Functions in JavaScript

Ignatius Sani
JavaScript in Plain English
5 min readOct 1, 2021

--

Photo by Dan Hadley from Pexels

Imagine we write a program that holds information about a user's purchased history, say the user modifies that data by removing an item, if part of the information gets lost, we have mutated the data. Hello guys, I've put this article together to help us write better programs by avoiding mutations that are mostly caused as a result of side effects.

Who this article is for?

This article is for anyone with at least a basic understanding of programming, specifically JavaScript. You should be sure to check free resources out there if this is not you. With that said, let's have some fun.

Getting Started

We will start off by understanding side effects and then proceed to know why pure functions are the common solutions to avoiding them.

What is a side effect in JavaScript?

When we modify something, in JavaScript, we cause side effects, this simply means modifying or changing our code, causing it to have unpredictable behavior and mutability. Let's understand this better by taking a look at this simple code snippet.

//side effectconst fruits = ['pineapple','orange','pawpaw','kiwi']function removeData(dataArr){return dataArr.pop()}removeData(fruits)

In this code, all we are doing is remove the last element from any provided array, the result, however, will mutate the original array which is not good if we must write a better program, imagine we have very useful data that we need to reuse in the future, this would make it impossible for us to do so, and clearly we can see the side effect here, which is our code being modified after we removed an element from the array.

Also, consider this example, imagine a user purchases some items, having a history of those items purchased will be handy if for instance there are some issues with the purchased item, even if the user made some modification in their cart by dropping an item, this should not get rid of the entire cart.

Let's take a look at one final example:

function sayHello(){console.log('Hello')}sayHello()

This code will also cause side effects, the reason being that console.log() belongs to the window objects, we always want to write predictable programs. I.e input should always be equal to output produced by functions.

Quality of good functions

In the next topic, I will be talking about pure functions and how they are a remedy to writing good programs, but it is also very important to understand what the character of good functions are, so I've put together just a few points to help you understand better.

  • 1 Task: A good function should perform one task at a time, it should focus on one thing and do it best.
  • Predictability: A good function should be predictable, this way we always expect the same input as output.
  • Composability: to compose in a program, we care about system design principle that deals with the relationship of components
  • Immutability: this means not changing data or state, but instead, make copies and also return new data.
  • Return statement: A good function must have a return statement.
  • Pure: Function is good when it doesn't cause side effects.
  • No shared state: To write a good function, we want to avoid state sharing.

How do we avoid side effects in our program?

One of the best ways to avoid side effects in our program is to use pure functions, remember when we were talking about the quality of a good function, we said a function must be pure to meet the requirements of a quality function. but what are pure functions?

Pure functions, what are they?

Pure functions are functions that return the same output no matter what input it is being given without causing any side effects. Since our goal is to avoid side effects, understanding what pure functions do help us to do just that.

// remedy for side effectsconst arr = [1,2,3]function removeItem(item){const newArr = [].concat(item);newArr.pop()return newArr}// console.log(removeItem(arr));// console.log(arr);

In the above code, all we are doing is removing an item from an array, the concat() method ensures we don't mutate the provided array by making a copy instead.

We also avoided global variables and used local variables instead, this will prevent access from the "outside world" i.e the variables can't be called outside the code block. Something we call scope in JavaScript, but I'm not going to talk about that here since it's beyond the scope of the article.

Why are pure functions the best solutions for side effects in JavaScript?

Well, for us to better understand this, we'll look at some significance of using pure functions.

Significance

  • Predictability: when we write pure functions, we always know what to expect because it has no effect on the outside variable.
  • Test: It makes the function easy to test.
  • Composition: composition is the act of using smaller pieces of code to create bigger ones the compose() method is an example of this. The pure function makes this possible.
  • Immutability: means inability to change a data or a state, by writing pure functions we make copies instead of changing the original data e.g
const obj = {name: 'iggy'}function clone(obj){return {...obj} // immutability (making copies)}function updateName(obj){const obj2 = clone(obj);obj2.name = 'sewa'return obj2}const updateObj = updateName(obj)

Here, changing the name-value will not mutate the object, because by using the spread operator we made a copy of everything contained in the object.

Lastly, pure functions help us to minimize bugs in our program.

We can already tell why pure functions are the best solution to writing programs free of side effects, because of their numerous benefits,

It’s important to know that pure functions are concepts of functional programming, I just need to mention that here, since it’s quite impossible to talk about pure function without talking about functional programming, functional programming is all about separation of concerns, it is a way of making sure our code does one thing its good at and ensuring data are not mutated, this makes it the choice of most developers.

The overall idea behind this is to minimize side effects, which is beneficial when fixing bugs in our program because we know exactly where to go.

Conclusion

Side effects are not necessarily bad, but the goal here is to organize your code in a way that isolates things from each other. If you want to learn more about — side effects and pure functions. I recommend you check out this resource.

That’s it guys, I hope you all had fun reading through this article and, hope this helps you to write better programs with the help of pure functions, please don’t hesitate to ask me any questions if you’re are not 100% clear, I’m also open to feedback, so feel free to let me know what you think I should improve on.

Happy coding and thank you for reading!

More content at plainenglish.io

--

--

I'm a Ruby on Rails full-stack developer specializing in mobile and frontend development.