Notes on JavaScript functional programming
in Note with 0 comment
Notes on JavaScript functional programming
in Note with 0 comment

Finally, I took the time to do a simple sorting. The content is relatively basic. It is mainly the granulation of knowledge points, which is convenient to find and deepen understanding in the future. It can be regarded as notes

Functional programming

In short, "functional programming" is a "programming paradigm", that is, the methodology of how to write programs.

Functional programming belongs to declarative programming. Imperative programming is often discussed with declarative programming.

Declarative programming

Declarative programming generally means declaring (explaining) what the result you want is, and then returning it to you.

For example, now there is a group of transcripts, and I want to filter students with scores above 90, as follows

 let reports = [ { name: 'Tom', grade: 86 }, { name: 'Amy', grade: 94 }, { name: 'Mike', grade: 85 }, { name: 'Jack', grade: 79 }, { name: 'Nami', grade: 91 } ]

Declarative expression, as follows

 const declarativeReportFilter = (reports) => { return reports.filter((report) => report.grade >= 90) }

In the above function, it just explains what kind of results you want, that is, students with scores above 90.

Imperative programming

Ordinarily, imperative programming is to clarify how to get a result: first do this, then do this, then do this, if so, then do this

It is the original set of transcripts, imperative, as follows

Command:

 const imperativeReportFilter = (reports) => { let result = [] for (let i = 0; i < reports.length; i++) { if (reports[i].grade >= 90) { result.push(reports[i]) } } return result }

In the function, declare a result Variable, and then assign to an empty array. Then through for Cycle reports When cycling, judge whether the grade of the current project is greater than or equal to 90. If it is, put the project into result Inside. After the loop is completed, the processed result will be returned.

In imperative programming, each operation needed to get the result is described in detail.

Defining Functions

In JavaScript, functions are objects, so we can say that functions are first class citizens in JavaScript. The so-called "first-class citizen" means that functions are on an equal footing with other data types, and can be assigned to other variables, can also be used as parameters, can be passed into another function, or can be used as the return value of other functions.

Define a function:

 function greet(greeting, name) { return `${greeting}, ${name}` }

Because JavaScript is an object, it has some attributes and methods. such as name Property is the name of the function, length Property refers to how many parameters must be passed in a function. For example, access the two attributes in the function defined above:

 greet.name //Output Greet greet.length //Output 2

Function expression

A function is an object, or a value. In JavaScript, it is the same as other types of values, such as strings and numbers. This allows us to use the function expression method to define functions, that is, to define an anonymous function, and then give it to a variable. As follows:

 var greet = function (greeting, name) { return `${greeting}, ${name}` }

Lambda expression

ES6 allows us to use lambda expressions, that is, fat arrow functions, as follows:

 var greet = (greeting, name) => { return `${greeting}, ${name}` }

Make it simpler:

 var greet = (greeting, name) => `${greeting}, ${name}`

The item to the right of the arrow will be returned automatically.

Methods in objects

If a function is in an object, we generally call it a method of the object.

want a go:

 var obj = { greet: function (greeting, name) { return `${greeting}, ${name}` } }

ES6 allows us to define methods for objects as follows:

 var obj = { greet (greeting, name) { return `${greeting}, ${name}` } }

An object named obj is defined above, and a method named greet is added to it. To use this method:

 obj.greet('hi', ' 😙') //Return to "hi, 😙 ”

Pure function

Functional programming encourages us to create more pure functions. Pure functions only depend on what you give them. They don't use anything other than functions, nor will they affect anything other than functions. The corresponding to pure functions is impure functions, that is, impure functions may use things other than functions, such as a global variable. It may also affect things other than functions, such as changing the value of a global variable.

More pure functions are used because they are more reliable and have no side effects. If you give it the same value, it will output the same result to you every time. This characteristic is called referential transparency. This will make the program more stable and easier to test.

side effect

Pure functions have no side effects, and functions with side effects are impure. I took a cold medicine to cure my cold, but the side effect was that it made me want to sleep. The side effects of a function are mostly functional dependencies or changes to something other than it.

 let name = 'chakhsu' const greet = () => { console.log(`hello, ${name}`) }

Greet is not a pure function because it depends on something other than the function. Here is the name in the global scope. The problem is that the name of the function dependency is likely to change when the application runs. Try this:

 Greet()//Output: "hello, chakhsu" Let name='linpx'//The value of name is changed Greet()//Output: "hello, linpx"

Change it like this:

 const greet = (name) => { console.log(`hello, ${name}`) }

Now the function clearly explains what it needs. Here is name Parameters. It only depends on what you gave it name The value of the parameter. But this function is still not a pure function, because it outputs something on the console, which actually changes something other than the function, so it is not a pure function. Change it like this:

 const greet = (name) => { return `hello, ${name}` }

Now? greet It will be a pure function, because it only depends on the name It doesn't change anything other than functions. And you give it the same every time name Value, which will return the same result to us every time. This function is safe and reliable to use.

Referred transparency

Referential transparency. For example, I said: "The capital of China". My expression means "Beijing", there is no other implied meaning. So I can say that what I mean is transparent. Another example: "I'm a little hungry". This expression is not transparent. What I mean is uncertain. I may want to go out to eat something, or I may want you to buy something for me to eat.

Pure functions are transparent, because if you give them the same thing, they will return the same result every time

 const greet = (name) => { return `hello, ${name}` } const logger = (message) => { console.log(message) } //Same running result logger(greet('chakhsu')) logger('hello, chakhsu')

because greet The reference is transparent, so if we replace it with what it refers to in the expression, it will not affect the operation of the program. For example, in an expression greet('chakhsu') We can all greet('chakhsu') replace with hello, chakhsu , this is because greet('chakhsu') What it refers to is a string hello, chakhsu

Invariance

Immutability means that an object will not change after it is created. Things in functional programming generally have this feature. It is a good thing to make an object immutable. If the object needs to be changed, you should create a new object and include the changed part in the new object instead of modifying the object itself directly.

In JavaScript, strings and numbers are immutable. That is, once a string is created, its value will not change. But arrays or objects in JavaScript are mutable, so they can be used Object.freeze Freeze them (only one layer can be frozen), or use some external databases, such as Immutable.js

Experiment:

 let name = 'linpx.com' name[5] "." name[5] = '-' "-" name "linpx.com"

Try modifying it above name (replace the dot "." in linpx.com with "-"). Because the value of string cannot be changed.

Try again:

 let names = ['Tom', 'Amy', 'Mike', 'Jack'] names[0] = 'Tomii' "Tomii" names ['Tomii', 'Amy', 'Mike', 'Jack'] names.push('Nami') five names ['Tomii', 'Amy', 'Mike', 'Jack', 'Nami']

This time we tried to change the value of an array. In JavaScript, this is allowed. We changed the value of the original array (names). Some methods of array will also change the value of the original array. For example, we used push Method, in names A new item has been added, and this action modifies the original array names The value of.

Object.freeze

Object.freeze can freeze objects, but only one layer can be frozen.

Experiment:

 let names = ['Tom', 'Amy', 'Mike', 'Jack'] Object.freeze(names) ['Tom', 'Amy', 'Mike', 'Jack'] names[0] = 'Tomii' "Tomii" names ['Tom', 'Amy', 'Mike', 'Jack'] names.push('Nami') VM705:1 Uncaught TypeError: Can't add property 4, object is not extensible names ['Tom', 'Amy', 'Mike', 'Jack']

use Object.freeze Frozen the created names Array, when you want to modify names Array will not affect names The original value.

currying

I have written two articles about Curry( Portal 1 Portal 2 ), here is a brief supplement

Currying refers to making a function that accepts multiple parameters into a function sequence that only accepts one parameter at a time.

Take an example:

 const greet = (greeting, name) => { return `${greeting}, ${name}` } greet('hello', 'chakhsu') // “hello, chakhsu”

The above greet is a function that receives multiple parameters. If it is converted to a Currying style function, it will look like this:

 const greet = greeting => name => `${greeting}, ${name}`

The arrow function is used above. If it is written as a normal function, it should look like this:

 const greet = function(greeting) { return function(name) { return `${greeting}, ${name}` } }

greet Is a function that takes a parameter of greeting , this greet A function will be returned, and the returned function will receive another parameter: name In the returned function, the final result will be returned. The return here is to put greeting And name The values of the parameters are organized into a new string.

This function works like this:

 greet('hello')('chakhsu') // “hello, chakhsu”

Higher order function

In JavaScript, functions are no different from ordinary objects, so you can pass functions as parameters to other functions, and you can also return functions in functions. Functions that use functions as parameters or return functions are called higher-order functions.

example:

 const robot = (name, action) => { return action(name) } const greet = (name) => { return `hello, ${name}` } const greeting = robot('  🐶 ',  greet) //Return "hello, 🐶  ”

robot It is a function that supports two parameters, name And action , here action The type of the parameter is a function. stay robot It returns action , and put name The value of the parameter was given to action Next, we define a function called greet , which accepts a parameter of name , this function will return a string.

Then we used it robot This function sets the values of its two parameters, name The value of the parameter is ' 🐶 ' action The value of the parameter is the function we defined as greet. The result of implementation will be:

 hello,  🐶

We can define the following functions:

 const goodbye = (name) => { return `bye, ${name}` }

Then use it again robot Function:

 const byeBye = robot('  🐙 ',  goodbye)

This time, we will return to:

 bye,  🐙

Complete example:

 const robot = (name, action) => { return action(name) } const greet = (name) => { return `hello, ${name}` } const greeting = robot('  🐶 ',  greet) console.log(greeting) const goodbye = (name) => { return `bye, ${name}` } const byeBye = robot('  🐙 ',  goodbye) console.log(byeBye)

epilogue

I have looked up a lot of materials, examples and tutorials. Because they were notes a month ago, the reference materials I found at that time have been forgotten, so I have no reference this time. It's like this

More content, so far~

Responses