A pure function is a function that produces no side effects and always returns the same output when called with the same input parameters.
You can use pure functions to ensure your code is clean, maintainable and testable. These functions are perfect for these tasks because they are predictable and don’t change external state.
It is also easier to debug, which helps in developing complex software systems. Here we discuss pure functions in JavaScript, their characteristics and advantages.
Features of pure functions
For a function to be “pure”, it must meet several requirements.
Constant return value
A pure function should always return the same value for the same input, no matter how many times it is called.
For example, consider the function
function multiply(a, b) {
return a * b;
}
of times The function in the example above always returns the product of its two arguments. Given the same set of arguments, they have constant return values.
Calling this function several times with the same arguments will produce the same output each time. for example:
multiply(2, 3);
multiply(2, 3);
multiply(2, 3);
Or consider the following example.
function multiplyRandomNumber(num) {
return num * Math.floor(Math.random() * 10);
}multiplyRandomNumber(5);
multiplyRandomNumber(5);
multiplyRandomNumber(5);
of multiplication of random numbers The function above is impure because it returns a different result each time it is called. The results of this function are unpredictable, making it difficult to test components that rely on this function.
no side effects
A pure function must not have side effects. Side effects refer to changes in state or behavior outside the function’s scope, such as changes to global variables, console output, network requests, or DOM manipulation.
If a pure function has side effects, it is no longer pure because it affects external state and violates the principle of no observable side effects. Thus, pure functions avoid side effects and avoid changing program state.
For example, consider the following example.
let count = 0;function increment() {
count++;
console.log(count);
}
increment();
increment();
increment();
of Increment The function in this example has count Variables out of scope. It also logs to the console.
This function has side effects and is not pure. This can make output difficult to predict and test in isolation.To make it pure, change it to count Takes a variable as an argument and returns the incremented value without changing the external state.
It seems like:
function increment(count) {
return count + 1;
}increment(1);
increment(1);
increment(1);
version of Increment The function in the example above does not modify any external variables or record their values, so it has no side effects. Also, no matter how many times you call it, it will return the same value for the same input. So it’s a pure function.
Other features
When writing pure JavaScript functions, in addition to having a constant return value and producing no side effects, they should adhere to the following rules:
- A function must not modify its arguments. Instead, make a copy of the argument and modify the copy if the operation requires modification.
- A function must always have a return value. If a function has no return value or side effects, you can’t do anything!
- Functions should not depend on external state.
Advantages of pure functions
Pure functions have some advantages over non-pure functions, some of which are:
Testability
Pure functions are easier to test because they have well-defined input and output behavior. Also, pure functions do not depend on external state or side effects. So you can test them independently without worrying about dependencies or interactions with other parts of your program.
In contrast, testing impure functions that depend on external state or produce side effects can be more difficult. Because their behavior can depend on program state and other external factors. This can make it difficult to write comprehensive test cases and verify that your function behaves correctly in all scenarios.
memoization
Pure functions always produce the same output for the same input and have no side effects, so they are easy to memoize.
By relying on these properties and using memoization, we can cache the result of a pure function call for a given input. The function can return cached results the next time it is called with the same inputs.
Memoizing a pure function can improve program performance without worrying about interfering with program state, especially for expensive computations that repeatedly process the same input.
In contrast, impure functions can produce different results for the same input, depending on program state or external factors. This makes memoization difficult because cached results may no longer be valid if the function’s dependencies or external state changes between calls.
concurrent execution
Pure functions are thread-safe because they do not modify external state or produce side effects. You can run them concurrently without worrying about race conditions or synchronization issues.
In contrast, impure functions can be difficult to run in parallel because running them in parallel can interfere with each other or cause unexpected behavior. For example, two threads accessing and modifying the same global variable can overwrite each other’s modifications and produce inconsistent results.
pure and impure functions
You can write programs with a combination of pure and impure functions. This is because each type has a purpose.
Pure functions are easier to optimize, test, and parallelize, making them suitable for use cases such as functional programming, caching, testing, parallel programming, and data processing tasks.
However, impure functions pose challenges for testing and concurrency, but they are useful when working with mutable data structures or interacting with external systems and resources.