A pure function is one that has no side effects and just depends on its arguments to determine the return value. i.e., a function will always return the same value if it is called 'n' times at 'n' places in the program with identical arguments.
Let's look at an illustration to illustrate the distinction between pure and impure functions.
//Impure
let numberArray = [];
const impureAddNumber = (number) => numberArray.push(number);
//Pure
const pureAddNumber = (number) => (argNumberArray) =>
argNumberArray.concat([number]);
//Display the results
console.log(impureAddNumber(6)); // returns 1
console.log(numberArray); // returns [6]
console.log(pureAddNumber(7)(numberArray)); // returns [6, 7]
console.log(numberArray); // returns [6]
According to the aforementioned code examples, the Push function is impure in and of itself because it modifies the array and returns a push number index regardless of the parameter value. Contrarily, Concat takes the array and concatenates it with the other array to create a whole new array without any negative side effects. Additionally, the previous array is concatenated in the return value.
Keep in mind that Pure functions are crucial because they make unit testing simpler and eliminate the need for dependency injection and side effects. Due to their lack of adverse effects, they also prevent tight coupling and make it more difficult to break your application. By favoring const over let usage, these concepts align with the Immutability idea of ES6.
Note - It is not a side effect when a pure function calls another pure function; the calling function is still regarded as pure. (For instance, using Math.max() within a function.)
To be regarded as a pure function, a function must not cause the side effects listed below (but not exclusively):
- sending a request over HTTP
- changing data
- printing to a terminal or screen
- Query/Manipulation of DOM
- Math.random()
- Obtaining the time right now