This article is an extract from Anjana Vakil’s 2016 talk at JSConf. There are a lot of tutorials out there on functional programming, but I think this is the most concise. The speaker’s expression is very clear and smooth, conditionally friends strongly recommend watching the original video.
What is functional programming
Functional programming is expressing a program entirely in functions, passing arguments to functions, and then printing the results. When we have a list of data, we need to think about how to express it in the form of functions, rather than in the form of imperative programming line by line. Here’s an example:
Var greeting = "Hi I 'm" console.log(greeting + name) // Hi I'm AnjanaCopy the code
This is typical imperative programming, processing the first line first, followed by the second line. Let’s take a look at how to express this code in a functional way. It’s very simple and easy to understand:
function greeting(name) {
return "Hi i'm " + name
}
greeting("Anjana")
Copy the code
Pure functions and side effects
At the heart of functional programming is the use of pure functions to avoid pure effects. A pure function is one that uses only the arguments passed in to process the output. This has the advantage of returning the same thing every time you pass in the same arguments. Side effects are functions that use global variables or do not return results, making the function unmanageable. (Pure functions are concerned with handling the contents of the function and returning the result, so a function with console inside is not pure, even though it returns void.)
Function print(){console.log("test")} or var name = "Anjana" function getName(){return name}Copy the code
Print and getName are not pure functions.
Higher-order functions
The second key point of functional programming is higher-order functions. Higher-order functions are functions that can be passed as arguments to another function or returned within a function:
function makeAdjectifier(adjective) {
return function(string) {
return ajective + ' ' + string
}
}
var coolifier = makeAdjectifier("cool")
coolifier("conference")
// cool conference
Copy the code
Do not use iterate (no iterate)
In functional programming, instead of using for or while loops, use higher-order functions such as Map, Reduce, or Filter. I won’t focus on how these three functions are used here, but I’ll use a graph to show you what map and Reduce are:
(This is a really good image, and the comments on YouTube are saying that this is a very good image, but if you think about it, it’s like this.)
Avoid variable data
In actual development, we often encounter situations that change the data content:
var rooms = ["H1", "H2", "H3"]
rooms[2] = "H4"
console.log(rooms)
=> ["H1","H2","H4"]
Copy the code
In this example, we wanted to modify H3 in the array Rooms for various reasons, so we changed the second item of the array directly. Be aware that this can lead to all kinds of unforeseen problems, especially during collaborative development, where other people may not know that we’ve changed the array, and debugging can be a pain in the neck.
A better solution is to make rooms immutable data, so that no matter who uses them and when, they still look the same.
var rooms = ["H1", "H2", "H3"]
var newRooms = rooms.map(item => {
if(item === "H3") return "H4"
else return item
})
newRooms => ["H1", "H2", "H4"]
rooms => ["H1", "H2", "H3"]
Copy the code
In this way, rooms are guaranteed to be immutable, which also reduces the BUG rate of your code. Now, you might ask, if I have a very large amount of data, this copy is going to affect performance.
That’s right. Keep watching.
Reduce performance problems with immutable data by persisting data structures
As mentioned above, if I have a very complex piece of data, and I only change a little bit of data, I have to copy another piece of data to process it, which is very bad for performance. You can solve this problem by persisting data structures, and let’s see how it works.
Again in the previous example, we copied rooms so that we actually have two arrays in memory:
This good? This is not good.
So, the handling of persistent data structures looks like this:
Each item in the array is regarded as a child node of a tree. When we want to modify an item, we only need to create a new node and connect it to the tree. In this way, the data that does not need to be changed is reused, the performance loss is reduced, and the original data is guaranteed to be immutable.
Of course, we don’t need to do this in JavaScript, there are plenty of mature libraries for us to use. For example, I recommend Mori in the video, but I prefer Facebook’s immutable. Js because it may be used by more people in China.
That’s the end of the video. In fact, a long time ago in foreign countries began to push function programming, in fact, at the beginning I also think imperative programming is also good, write up easy to understand, others look convenient. But it was only after stepping into the mutable data pit (debug pain level is the highest) that I learned the importance of immutable data. So, if you want to change your code habits, start by installing immutable.