If you are a Javascript developer, chances are you have come across the term "Pure Functions". So, what exactly is a pure function?
Pure functions are the foundation of functional programming. For a function to be pure it must follow the rules below:
- Pure functions must be predictable
- It should not perform any side effects
Pure functions must be predictable
Now, what does this mean exactly?
And by 'this' I am not talking about the keyword 'this'. To this day, I still cannot define 'this'
๐ฌ
What does a function exactly do?
- Take an input
- Process it
- Give an output
Pure function takes at least one argument, processes it, and always returns the same output.
Let's see an example
const square = num => num * num;
console.log(square(5)); //25
In this example above, no matter how many times, the output would always be the same if you pass the same number.
let five = 5;
const incrementByFive = (num) => five+= num;
console.log(incrementByFive(5)); // 10
console.log(incrementByFive(5)); // 15
In the example above, our function depends on a global variable and mutates it. This gives us different output every time, even though we pass the same number.
This is why pure functions are predictive so that we can reuse them anywhere knowing what the output will be.
If your function is dependent on global variables then it is not a pure function. A pure function should return a value, based only on its arguments.
Pure function should not perform any side effects
Now, what are side effects?
Side effect includes DOM manipulation, data fetching, mutating functional arguments, etc.
Pure functions are meant to be reusable. If one of these functions starts DOM manipulation or data fetching then it will do it everywhere it is used.
What exactly do mutating functional arguments mean? Consider an empty cart
array and a product
object which needs to be added to the cart. Let's write a function to add items to this cart.
const cart = [];
const product = {
name: 'Headphone',
price: 2000
}
const addToCart = (cart, productToBeAdded) => {
cart.push(productToBeAdded);
return cart;
}
const newCart = addToCart(cart, product);
console.log(newCart); // [{name: 'Headphone', price: 2000}]
Great! Now we have a newCart
array in which we added our product. But is the original cart
array still the same? Let's see ...
console.log(cart); // [{name: 'Headphone', price: 2000}]
But we stored the value from the function in newCart
. Then why does this happen?
Array.push is a destructive method. When used it will mutate the existing array.
It is not a good practice to mutate an existing array. Why? Other functions may be using the cart
array, but now that we mutate it we have to worry about how it will affect the output of the other function in which it is being used.
Now that we know what mutating an argument means, how can we avoid it? We simply use the Spread syntax (...) which lets you copy all the existing elements on an array or object.
const cart = [];
const product = {
name: 'Headphone',
price: 2000
}
const addToCart = (cart, productToBeAdded) => {
return [...cart, productToBeAdded];
}
const newCart = addToCart(cart, product);
console.log(newCart) // [{name: 'Headphone', price: 2000}]
console.log(cart) // []
You can also overwrite existing values in an array or object using the spread syntax without mutating the original array or object.
Conclusion
Pure functions are simple reusable functions that take at least one argument, processes it, and give an output.
Pure functions should always return a value or other function.
Pure functions should not have any side effects.
Does this mean you should only use pure functions in your application? Of course not, we always need impure functions to run our side effects.
Thank you for reading till the end ๐ Let me know in the comments if you like the blog or if you have any suggestions!