Why learn functional programming
JavaScript has important features needed for functional programming:
- First-class functions: Ability to use functions as parameter values: Ability to pass functions as arguments, return functions, and assign values to variables or objects. This property allows higher order functions, function combinations, currization, and so on.
- Anonymous functions with concise lambda syntax: for example x => x*2 is a valid JavaScript expression.
- Closures: CLOSURES are a combination of a function and the lexical environment in which the function is declared. When a function is defined within another function, the variables defined by the external function can be accessed even after the external function has exited.
JavaScript is a multi-paradigm language, which means it supports many different styles of programming. But multiparadigm programming has an important drawback, which is that imperative and object-oriented programming can lead to everything being mutable and uncertain. For example:
const foo = {
bar: 'abc'
};
foo.bar = 'def' // Foo has changed
Copy the code
In general, objects are mutable so that their properties can be updated by methods. In imperative programming, most data structures are mutable to enable efficient manipulation of objects and arrays.
Here are some features that functional languages have that JavaScript does not:
- Pure functions: In some functional programming languages, pure functions are implemented language-wise and side-effect expressions are not allowed.
- Immutability: Some functional programming languages do not allow mutations. Instead of changing existing data structures (objects and variables), expressions are evaluated as new properties and returned.
- Recursion: Recursion is the ability of a function to call itself for the purpose of iteration, and in many functional programming languages, recursion is the only way to iterate. There are no loop statements similar to while or for loops.
Pure functions
Properties of pure functions
1. Given the same input, the same output must be returned
// Enter the same value, return the same result
const highpass = (cutoff, value) = > value >= cutoff;
highpass(5.5); // => true
highpass(5.5); // => true
highpass(11.2); // => false
highpass(11.2); // => false
// The following code is not pure
Math.random(); / / = > 0.4011148700956255
Math.random(); / / = > 0.8533405303023756
Math.random(); / / = > 0.3550692005082965
Copy the code
2. There are no side effects, which means it can’t change any external states
// A function with side effects
const addToCar = (car, item, quantity) = > {
cart.items.push({
item,
quantity
});
return car;
};
// The original object
const originalCar = {
items: []};const newCar = addToCar(
originalCar,
{
name: 'BMW'.price: '99'
},
1
);
console.log(JSON.stringify(originalCar, undefined.2));
// Log can see that the addToCar method changes the external originalCar object
{
'items': [{'item': {
'name': 'BMW'.'price': '99'
},
'quantity': 1}}]Copy the code
// Function with no side effects
const addToCar = (car, item, quantity) = > {
return {
car,
items: car.items.concat([{
item,
quantity
}]),
};
};
const orignalCar = {
items: []};const newCar = addToCar(
originalCar,
{
name: 'BMW'.price: '99'
},
1
);
console.log(
JSON.stringify(originalCar, undefined.2)); Logs: {'items': []}Copy the code
A function call can be replaced with its resulting value without changing the meaning of the program
const addX = x= > {x += 1}
myX = addX(2) / / 3
/ / is equivalent to
myX = 3
Copy the code
Pure functions have many beneficial properties and are the foundation of functional programming. Pure functions are completely independent of the external state, independent of some of the bugs caused by the external mutable state. Their independence also makes them the best choice for parallel processing across multiple cpus and entire distributed computing clusters, making them critical for many types of scientific and resource-intensive computing tasks. Pure functions are also very independent, easy to move in the code, reuse, reorganization, so that the program becomes more flexible.
Shared state
What is shared state
A shared state is any variable, object, or memory space that exists in a shared scope, or as a property of objects passed between scopes, which can include a global scope or a closure scope.
The sharing status is faulty
In development, we often use an ajax request for data, I think we must have most of the developers used input box input lenovo query, when the user input in the process, each input to trigger a request, used to obtain the candidate item data, because the user’s input speed is often faster than the response speed of the API, this way will lead some strange questions, For example, the latest data that we actually need to get is replaced by old data. This is because the slowest Ajax request always supersedes the latest result, leading to unexpected errors. Contention conditions (wait time, user input, randomness, etc.) can occur if the output depends on the order of events that cannot be controlled (such as network, device). Just because JavaScript is run single-threaded doesn’t mean that concurrency doesn’t exist.
const x = {
val: 2
};
const x1 = (a)= > x.val += 1;
const x2 = (a)= > x.val *= 2;
x1();
x2();
// Will change the external x value
console.log(x.val) / / 6
Copy the code
We can refactor the above code:
const x = {
val: 2
};
const x1 = x= >({... x,val: x.val + 1});
const x2 = x= >({... x,val: x.val * 2});
x1();
x2();
console.log(x2(x1(x)).val); / / 6
console.log(x.val) / / 2
Copy the code
Changes to one function, or calls to one function, do not affect other parts of the program
invariance
Immutable objects are created objects that cannot be modified. Immutability is a core concept of functional programming, because without it, the data flow in the program would be lost, the history of state would be lost, and unpredictable errors would result. In JavaScript programming, we cannot confuse const declarations with immutable objects. An object created by const cannot change the bound reference object, but you can still change the properties of the reference object, which means that objects declared by const are mutable. JavaScript has a method for freezing a level 1 object:
const a = Object.freeze({
foo: 'Hello'.bar: 'world'.baz: '! '
});
a.foo = 'GoodBye';
// Error: Cannot assign to read only property 'foo' of object Object
Copy the code
This method can freeze only first-level objects:
const a = Object.freeze({
foo: { greeting:'Hello' },
bar: 'world'.baz: '! '
});
a.foo.greeting = 'GoodBye';
console.log(`${ a.foo.greeting }.${ a.bar }${a.baz}`); // 'Goodbye, world! '
Copy the code
We can freeze objects at all levels by deep traversal. Here are two libraries for freezing objects, Immutable. Js and Mori
Side effects
A side effect is any observable change in application state outside of the function being called, rather than its return value. Side effects include:
- Modify any external variables or object properties (for example, global variables or variables in the parent function scope chain)
- Log in to the console
- Written to the screen
- Written to the file
- Written to the network
- Trigger any external processes
- Call other functions that have side effects