“This is the 12th day of my participation in the First Challenge 2022. For details: First Challenge 2022”
Now that I’ve covered a few features of functional programming, I’ll cover the last one: pure functions
Pure functions
Pure functions take the “no side effects” requirement one step further. You’ve come across this term in many places, but in the Three Principles of Redux, we see that all modifications must use pure functions.
Changes are made with pure functions
In fact, the concept of pure functions is very simple:
- Independent of external state (stateless) : The result of a function does not depend on global variables, this Pointers, IO operations, etc.
- No side effects (unchanged data) : No modification of global variables, no modification of input parameters.
So pure functions are “functions” in the true sense of the word, meaning that the same input will always get the same output.
The following functions are not pure because they rely on external variables. Imagine if someone called changeName to modify curUser, and then you called saySth somewhere else, which would have unexpected results.
const curUser = {
name: 'Peter'
}
const saySth = str= > curUser.name + ':' + str; // global variables are referenced
const changeName = (obj, name) = > obj.name = name; // Modify the input parameters
changeName(curUser, 'Jay'); // { name: 'Jay' }
saySth('hello! '); // Jay: hello!
Copy the code
What happens if I write it as a pure function?
const curUser = {
name: 'Peter'
}
const saySth = (user, str) = > user.name + ':' + str; // Do not rely on external variables
const changeName = (user, name) = >({... user, name });// External variables are not modified
const newUser = changeName(curUser, 'Jay'); // { name: 'Jay' }
saySth(curUser, 'hello! '); // Peter: hello!
Copy the code
So we don’t have any of those problems.
What is the point of using pure functions when we put so much emphasis on them?
- Easy to test and optimize: This makes a lot of sense in real project development, because pure functions always return the same result for the same input, so we can easily assert the result of the execution of the function, and also guarantee that the optimization of the function will not affect the execution of other code. This is very much in line with test-driven Development (TDD), which tends to produce more robust code.
- The cache can be: Because the same input can always return the same output, we can cache the result of the execution of the function ahead of time, there are many libraries that have what is called
memoize
The function, let’s do a simplified version of itmemoize
For example, this function can cache the result of the function for the imagefibonacci
This calculation can play a very good caching effect.
function memoize(fn) {
const cache = {};
return function() {
const key = JSON.stringify(arguments);
var value = cache[key];
if(! value) { value = [fn.apply(null.arguments)]; // Put it in an array to handle undefined, null and other exceptions
cache[key] = value;
}
return value[0]; }}const fibonacci = memoize(n= > n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2));
console.log(fibonacci(4)) Fibonacci (2), Fibonacci (3), Fibonacci (4)
console.log(fibonacci(10)) // the results of Fibonacci (2), Fibonacci (3), Fibonacci (4) are fetched directly from the cache, while the others are cached
Copy the code
- Self-documentation: Because pure functions have no side effects, their dependencies are clear and therefore easier to observe and understand.
- Fewer bugs: Using pure functions means that your functions have no references to obscure this, no references to global variables, and no modifications to parameters, which are the source of most bugs.