Why learn functional programming
- Functional programming is getting more attention with the popularity of React
- Vue3 is also embracing functional programming
- Functional programming can discard this
- Better use of Tree Shaking to filter out useless code during packaging
- Convenient for testing and parallel processing
- There are many libraries that can help us with functional development (e.g., the following three libraries)
-
Lodash (https://www.lodashjs.com/) is a consistency, modular, high-performance JavaScript utility library.Copy the code
-
Unnderscore (https://underscorejs.net/) is a JavaScript library, provides a set of functional programming and practical function, but does not extend any built-in JavaScript objectCopy the code
-
Ramda (https://ramda.cn/) is a useful JavaScript functional programming library designed specifically for the functional programming style, making it easier to create functional pipelines without changing user data.Copy the code
ProgrammingParadigm (I believe that most developers and dbas have heard of the word paradigm, there are first paradigm, second paradigm, third paradigm, BCNF paradigm in MySQL, there are corresponding paradigms in development, the professional term is called ProgrammingParadigm) as shown below
The following programming methods are mainly explained
- Functional programming -> Abstracts the relationships between real things into the program world (abstracts the process of computation)
- Process oriented programming -> Follow the steps to achieve the desired function step by step
- Object oriented programming -> Abstracts real things into classes and objects, demonstrates the relationship between things and events through inheritance encapsulation and polymorphism (abstract real things)
The functions of functional programming are not functions (methods) in programs, but relationships of mapping methods in mathematics. So y is equal to sine of x, the relationship between x and y. Always keep the same input, always get the same output (pure function concept) Functional programming is used to describe the direct mapping of data (functions). The advantage is that you can reuse your code, and you can abstract out the Currified functions, and you can combine them according to your own composition
Let’s take a simple example
Let a = 1 let b = 2 let c = a + b console.log(c) Js function add(a, b){return a + b} let a = add(1,3) console(a)Copy the code
Functions are first-class citizens.
Functions can be stored in variables. Functions can be arguments. Functions can be return values
- In JS, a function is just an ordinary object, via new function(). We can store a function in a variable/array, use it as an argument and return value of another function, or even construct a new function while the program is running by using new function (alert(1))
Assigning a method of a function to another function or method is equal. For example, the following codeconst test = {
index(arg):{return Views.index(arg)}
}
/ / optimization
const test = {
index: Views.index
}
Copy the code
Higher-order functions
- You can pass a function as an argument to another function
- You can treat a function as the return of another function
- Functions as arguments (to make functions more flexible)
For example, write a higher-order function (foreach, filter, map, every). These higher-order functions are returned by functions
// Self-encapsulated foreach
function foreach (array , fun){
for(i=0; i<array.length; i++){ fun(array[i]) } } foreach([1.2.3].(e) = >{
console.log(e)
})
Copy the code
// self-wrapped filter, for example I want to find an array greater than 10
function filter (array , fun){
let result = []
for(i=0; i<array.length; i++){if(fun((array[i]))){
result.push(array[i])
}
}
return result
}
let list = filter([1.20.3.40].(item) = >{
return item>10 ? true : false
})
console.log(list)
Copy the code
// The map can only loop through arrays, each number +1
function map (array , fun){
let result = []
for(let value of array){
result.push(fun(value))
}
return result
}
let list = map([1.20.3.40].item= > item+1)
console.log(list)
Copy the code
// every is greater than 0
const every = function(array , fun){
let result = true
for(let value of array){
if(! fun(value)){ result =false
break}}return result
}
let list = every([1.20.3.40].item= > item>0)
console.log(list)
Copy the code
- Function as the return value
function makeFun(){
letMSG = "hellow"return function(){
console.log(msg)
}
}
// Returns a function
const fun = makeFun()
// Execute the function
fun()
// Or execute directly
makeFun()()
Copy the code
// Self-encapsulated once
function once(fun){
let done = false
return function(){
if(! done){ done =true
return fun.apply(this.arguments)}}}let list = once(e= >{
console.log(It took `${e}Yuan `)
})
list(5)
list(5)
list(5)
Copy the code
Meaning of higher order functions
- Abstraction can help us mask the details and just focus on the goal
- Higher-order functions are used to abstract general problems, and they allow us to be flexible
closure
- You can call a function inside a function from another scope and access members of the function’s inner scope
- The essence of closures: Functions are placed on the stack for execution, and removed from the stack when the function completes execution, but scoped members on the heap cannot be freed because they are referenced externally, so internal functions can still access external function members
// For example
let makeFun = function(){
let msg = 'hellow'
return function(){
console.log(msg)
}
}
console.log(makeFun()())
Copy the code
Now use closures to encapsulate a power of 10 to the 2nd
function pow(y){
return function(x){
return Math.pow(x,y)
}
}
let a = pow(2)
let b = a(10)
console.log(b)
Copy the code
Pure function (concept of function in mathematics)
- Pure function: the same input always yields the same output, y=f(x) such as f is the process
-
Lodash (www.lodashjs.com/) is a consistent, modular… JavaScript utility library. Is a pure function library, provides some methods on arrays, strings, functions
-
For example, slice and splIEC in arrays are pure and impure functions, respectively. Because Splice changes the array
// Write a pure function
function add (a,b){
return a+b
}
// There will always be a result
console.log(1.3)
Copy the code
** Functional programming does not preserve the results in the middle of the computer, so variables are immutable (stateless) and we can pass the results of one function to another to process **
Simple use of Lodash
const _ = require('lodash')
const arr = ['d'.'r'.'3'.'dd'.'kk']
console.log(_.first(arr))
console.log(_.last(arr))
Copy the code
Benefits of using pure functions
const _ = require('lodash')
//memoize
// Calculate the area of the circle
function geArea(r){
console.log(r)
return Math.PI * r *r
}
let getAreaM = _.memoize(geArea)
console.log(getAreaM(4))
console.log(getAreaM(4))
/ / 4
/ / 50.26548245743669
/ / 50.26548245743669
Copy the code
- Can be cached
- Testable (pure functions are easy to test)
- Parallel processing
- Operating on shared memory in parallel in a multi-threaded environment can lead to unexpected situations (multiple threads modifying a variable at the same time)
- Pure functions do not need to access shared memory data, so they can be run in parallel (Web workers are multithreaded, js is single-threaded, but can be multithreaded).
// impure function
let mini = 10
function age (num){
return age
}
// Since let mini = 18 is a global variable, it is possible to change the result if contaminated, so when placed inside the function, it becomes a pure function
// Pure function (hard coded, can be solved by Currization)
function age (num){
let mini = 10
return age
}
Copy the code
- A side effect makes a function impure. A pure function returns the same output based on the same input.
- Sources of side effects:
The configuration file database retrieves external factors such as user inputCopy the code
- Side effects are inevitable, so we try to control them as much as possible
Currie,
Function currification: When a function has more than one argument, we can modify the function by calling a function, passing only some arguments (which never change), and making the function return the new function, which takes the remaining arguments and returns the corresponding result
// Currization function
// min is a parameter that never changes
let checkAge = min= > (age= > age >= min)
let chec20 = checkAge(20)
console.log(chec20(19))
Copy the code
- The Curry function in Lodash uses (_.curry()=> to create a function that can pass one or more fun functions with all the arguments executed, otherwise it waits to receive arguments, and returns a Currified function when it is finished.)
Corrified summary
- Currization allows us to produce a new function, and the new function, which already records fixed arguments, uses closures that hold some of the passed arguments,
- Is a caching of functions, using closures to cache parameters
- Make the function more flexible, make the function less granular
- Can turn multivariate function into unary function, can compose use function to produce powerful function
Function combination binding rate
Function combination rate: Combine functions. The answer is the same whether it’s g with f, or f with g
// The following is equal
const f = _.flowRight(_.toUpper,_.first,_.reverse)
const f = _.flowRight(_.flowRight(_.toUpper,_.first),_.reverse)
const f = _.flowRight(_.toUpper,_.first,_.flowRight(_.reverse))
Copy the code