What Are Side Effects in Javascript? What Are Pure Functions?
Pure functions and function programming is something that can bring your Javascript code to the next level.
In this tutorial you will learn:
- Why pure functions are important?
- When you code is impure (mutable)
- What hidden problems of function parameters we have
- What are side effects?
- Why you need to write pure immutable code
Why pure functions are important?
So what are pure functions and why should you care? It's a function without side effects. It means that function will always no matter what return the same result with the same arguments. Here is a simple example.
let tax = 20;
const calculatePriceWithTax = (productPrice) => {
return (productPrice * tax) / 100 + productPrice;
};
This is the typical example of bad impure code. So here we define tax outside of our calculatePriceWithTax function. But then we use this variable inside. Using variables from outside of the functions is one of the ways to make our function impure. It is bad. Why? Because our function will produce different result in different time because when this property outside will be changed we might be not aware of that.
You might say that it's clear in this example what is happening but imagine if you have a project with hundreds lines of code. This is why making function pure will help your code tremendously.
How we can refactor it to pure? We can either move tax property inside a function or accept it as an argument.
Variant 1
const calculatePriceWithTax = (productPrice, tax) => {
return (productPrice * tax) / 100 + productPrice;
};
In this case we get tax as an argument and we never use variables outside of our function.
Variant 2
const calculatePriceWithTax = (productPrice) => {
const tax = 20;
return (productPrice * tax) / 100 + productPrice;
};
In this case have tax a variable inside and we never use variables outside of our function.
We have more impure code
But it's not the only case of impure code. Using Math.random or new Date() is also a side effect as every usage of them generates new data. Which means they can't return the same result on the second call.
Using Math.random
const isImpure = () => {
return Math.random();
};
Using new Date()
const isImpure = () => {
return new Date()
};
What hidden problems of function parameters do we have?
But returning the same result is not the only rule of pure functions. Pure functions are not allowed to mutate external state because this behavior is super difficult to debug.
Here is the typical example where all beginner developers make a mistake.
const addToCart = (cart, item, quantity) => {
cart.items.push({
item,
quantity,
});
return cart;
};
This code might look completely normal. We get a cart with our items which is just an object, an item that we need to add and a quantity. A lot of people write code like this. But this code is not pure because push mutates array outside of our function. It doesn't matter that we return cart here because with push we already changed external data (variable cart) that we got as an argument. It's even worse because seeing the return you might think that this function is pure and "just returns data".
Image that you debug a bug in application where some data is randomly changed. Most often it's a case for mutating external state like we do here. What is the solution? Never use Javascript functions that mutate data. Instead of push we can use spread operator and generate a new array.
const addToCart = (cart, item, quantity) => {
return {
...cart,
items: [...cart.items, { item, quantity }],
};
};
Here we create new object and merge all properties of cart inside. After this we update our items array with new object of item and quantity. And yes this code looks much more difficult to understand than array push but it's much more stable, easier to debug and pure.
What are side effects?
Side effects is something that makes our function impure by default. Any asynchronous processes or working with things outside of Javascript are side effects.
Typical examples of side effects are:
- Working with API,
- Working with Localstorage,
- Reading or updating DOM tree
- Using web sockets
- Printing data on screen
- Writing data in logs.
Conclusion
It's important for you as a developer to understand the difference between pure and impure code. Also writing code in pure way will make your code less errors prone, easier to debug and support.
And it doesn't mean that all your functions must be pure, it's just not possible but I highly recommend you to write most of the code in pure manner. This will help you to become a much better developer.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!