Introduction: welcome to woo's front end. What we bring you today is advanced knowledge of JavaScript. The next series focuses on advanced JavaScript. First, we talk about advanced functions.
Definition of high-order function: high-order function refers to the function of operation function; generally, there are two situations in the process of project development
- Functions can be passed as arguments to another function for execution
- Function can be executed as a return value output
Let's use a graph to describe higher-order functions
These are the requirements of higher-order functions. The JavaScript functions we used in the development project obviously meet the requirements of higher-order functions; therefore, we can use higher-order functions to encapsulate the business logic of the basic functions again, or as callback functions. Next, let's start to see how to use higher-order functions in normal business; how to encapsulate higher-order functions? ,
First mode: pass as parameter
In business code, we often encounter two cases where the basic function logic is the same but the business logic is not used; we can encapsulate these two same logic into a higher-order function, so as to write different logic in the function as parameters and transfer it to the encapsulated function. In this way, we can realize some unchanged scenarios of business logic changes. This is our most common scenario; it is called callback function for short.
Let's give you an example
Example 1:
1 //Two different functions, but one part of the logic is the same and the other part is variable
2 function a(){
3 console.log("I'm a function");
4 console.log("I am a function");
5 }
6
7
8 function b(){
9 console.log("I'm a function");
10 console.log("I am b function")
11 }
12
13 /*
14 These are our two basic functions. We execute these two functions respectively
15 */
16
17 a();
18 b()
This is the result of our execution above. We can find that the two functions have the same point. So let's do the next step for the two functions
function c(fn){
console.log("I'm a function")
fn()
}
//Encapsulate the same logic into a c function, and pass the different logic into fn parameter function for execution
c(function(){
console.log("I am a function")
})
c(function(){
console.log("I am b function")
})
//This shows that we can achieve the presentation we want. Next, let's look at the result of execution
This is the result of our final execution. It is the same as the execution result above. It can be seen that higher-order functions can make the code more variable, more concise and understandable. This is a common scenario in our daily life.
Example 2:
In fact, there is another scenario that we often encounter in the project. We often use ajax requests or axios requests and other asynchronous requests in projects; generally, we don't care about the request process (the request process is the same) and only want the result of the request to process different business logic. We can use higher-order functions to encapsulate requests, also called request interception
var httpsAjax = function(obj,callback){
var {url,data,type} = obj;
$.ajax({
url:url,
type:type || 'POST' ,
data:dara || {},
success:function(res){
//Use typeof to determine the data type. If the function is passed in, we will execute the callback function
if(typeof callback === 'function'){
callback(res)
}
}
})
}
httpsAjax({
url:"xxx/get/user",
type:"GET",
data:{}
},function(res){
//Operate certain business logic
console.log(res)
})
Summary of the first mode: the above is the use of our most common basic higher-order functions. Generally, we use functions as parameters to pass to another parameter, and then another parameter executes the passed function, thus forming a callback function (higher-order function)
Second mode: output as return value
There are many application scenarios in which functions are output as return values instead of being passed as parameters. Let the function continue to return an executable function, which means that the operation process can be continued. For example, we often use array sorting Array.sort() method
Here are a series of isType functions that use the Object.prototype.toString method to determine the data type:
var isString = function(obj){
return object.prototype.toString.call(obj) === '[object String]'
}
var isArray = function(obj){
return object.prototype.toString.call(obj) === '[object Array]'
}
var isNumber = function(obj){
rturn object.prototype.toString.call(obj) === '[object Number]'
}
isString("I am an array string");//true
isArray(["1","2"]);//true
isNumber(1)//true
Note: in fact, we will find that the above three methods have most of the same logic object. Prototype. ToString. Call (object). The difference is to process the string results returned by logic. To avoid redundant code, we encapsulate it as a function is_type();
var is_type = function(obj,type){
return object.prototype.toString.call(obj) == '[object ' + type + ']'
}
console.log(is_type(11,'Number'));//true
console.log(is_type(['a','b'],"Array");//true
Note: the above is our encapsulation method. It can be found that after we extract the code, the amount of code is much less and more clear. However, we will find that we need to pass two parameters, and the meaning of the two parameters should be one-to-one. Otherwise, once we write the wrong business code without corresponding, the logic we write will appear a bug. So we encapsulate this method again, passing the type first as a parameter, using high-order function to save variables, returning a function, and analyzing what type of obj we passed.
var isType = function(type){
//First, a type parameter is passed as the data type, and the high-order function is used to save the variables, and a sustainable function is returned
return function(obj){
return object.prototype.toStirng.call(obj) === '[object '+ type +']'
}
}
//First, we can subdivide each type, so that we can know exactly what method is called by the specific type
var isString = isType("String");
var isArray = isType("Array");
var isNumber = isType("Number");
console.log(isArray([1,2,3]))//true
Summary of the second mode: the above is an example of our second mode. Obviously, we can use this mode to return one function to another, and let the operation of the function continue. This is the second mode as the return value output
The above is the basic understanding and demonstration of the two modes of higher-order function. I believe it will help you a lot in normal development projects. At the same time, we should also pay attention to that not every method in normal development projects needs to use higher-order functions, and the use scenarios of higher-order functions are the above two. Otherwise, it will lead to overuse. Next, let's talk about the four methods of high-order functions map()/reduce(), filter(), sort() that are often used in JavaScript.
-
map() method
- Definition: the map() method traverses the original array to return a new array. The elements in the array are the values after the original array elements call the function to process, and the elements are processed in order according to the original array elements.
- Note: empty array will not be detected, but the new array will not change the original array
- Syntax format:
newArray.map(function(item){
//Traversal newArray item is a newArray element; similar to newArray[i]
return item
//There must be return. No new array will be generated anyway
})
The map() method is defined in the JavaScript array. We call the array map method, pass in the function we want, and wait for a new array as the result:
Example:
function pow(x){
return x*x
}
var arr = [1,2,3,4,5];
console.log(arr.map(pow));//[1,4,9,16,25]
This is a simple map method call, passing a pow custom function, multiplying each element of the original array by a power, and getting a new array
For another example, we often encounter this kind of problem. We need to take an attribute from an array object to make a group of arrays
Example:
var arr = [
{
name:"Zhang San",
type:2
},
{
name:"Li Si",
type:3
}
]
//Request to get the type attribute to form a new array
//Previous writing method for loop
var new_arr = []
for(var i = 0 ; i < arr.length ; i++){
var obj = arr[i]
for(var key in obj){
if(key == 'type'){
new_arr.push(obj[key])
}
}
}
//The way to write map
var new_arr = arr.map(function(item){
return item.type
})
From the above, we can see that one writing method is for loop, and the other is map. Although the two results are the same [2,3], the for loop is too redundant and the map is simple and convenient in terms of code quantity. So it is more convenient to use the map method in the future
2.reduce() method
1. Definition: receive a function as an accumulator, traverse each value in the array (from left to right), and finally calculate it as a value
2. Note: callback function will not be executed for empty array
3. Syntax format: new Array.reduce(callback,initialValue)
Understanding of grammatical forms:
reduce(callback,initialValue) will pass in two variables, the first parameter is the callback function and the second initial value.
The first parameter callback function has four incoming parameters, prev and next, index and array. Prev and next are required parameters.
The initial value of the first parameter determines the value result of prev, the first parameter of the callback function. When reduce passes in the initial value, the default value of prev is the initial value. When reduce does not pass in the initial value, the default value of prev is the first element value of the original value.
Let's explain
var arr = ["apple","orange"];
//The first case where initialValue is not passed
function getValue(){
return arr.reduce(function(prev,next){
console.log("prev",prev);
console.log("next",next)
return prev;
})
}
console.log("getValue",getValue())
Running results show that we did not pass initialValue. prev is the first element value of arr to start traversal
Let's take a look at the delivery of initialValue
var arr = ["a","b"];
//When the initialValue case is passed
function getValue(){
return arr.reduce(function(prev,next){
console.log("prev",prev);
console.log("next",next);
prev[next] =1;
return prev;
},{})
//initialValue passes an empty object
}
console.log("getValue",getValue());
You can see the result of our operation. When you pass the initialValue, the default value of prev is the initialValue you pass; and we can use the default value to carry out a series of business logic processing. Achieve the effect we want
Next let's look at how reduce() is used in the regular business.
Case 1: calculating the sum of arrays
var numArray = [1,2,3,4,5];
//Calculate with for loop
var num = 0;
for(var i = 0 ; i < numArray.length ; i++){
num = num + numArray[i]
}
console.log(num);//15
//Using reduce method
var res = numArray.reduce(function(prev,next){
return prev + next
},0)
console.log(res) ;//15
With the for loop, we first declare a global variable as the default value. We know that in the process of developing a project, we should try not to use global variables, but we can completely avoid using reduce, which is more direct. This is a simple use of reduce().
Case 2: merging 2D arrays
var arr = [[0,1],[2,3],[4,5]];
var res = arr.reduce(function(prev,next){
return prev.concat(next)
},[])
console.log(res);//[0,1,2,3,4,5];
We can pass an empty array as the default value and merge the original array elements into a new array.
Case 3: count the repetition of words in an array
var arr = ["apple","orange","apple","orange","pear","orange"];
//When you don't use reduce
function getWorad(){
var obj = {};
for(var i = 0 ; i < arr.length ; i++){
var item = arr[i];
if(obj[item]){
obj[item] = obj[item] + 1
}else{
obj[item] = 1
}
}
return obj
}
console.log(getWorad());
function getWorad2(){
return arr.reduce(function(prev,next){
prev[next] = (prev[next] + 1 ) || 1;
return prev;
},{})
}
console.log(getWorad2())
The last two results are the same, in fact, we use the reduce() method to make our logic simple and easy to handle. So we can discard our redundant code and make it more clear. I believe you will encounter this kind of business logic in your normal business.
3. filter() method
1. Definition: filter() is also a common operation. It is used to filter some elements of Array, and then return the remaining elements. Similar to map, Array's filter also receives a function, which is different from map(). Filter() applies the incoming function to each element in turn, and then determines whether to keep or lose the function according to whether the return value is true or false element
Case column 1: for example, in an Array, delete even numbers and keep only odd numbers. You can write as follows:
var arr = [1,2,3,4,5];
var r = arr.filter(function(item){
return item%2 !== 0 ;
})
console.log(r)
As you can see, we use filter to filter the elements. As long as the residual of the elements is not equal to zero, we will return, discard if it is equal to zero, and finally form a new array.
Case 2: remove the empty string in an arr and write as follows:
var arr = ['a','b','','c']
var r = arr.filter(function(item){
return item && item.trim();
})
console.log(r)
We can use filter to filter the empty strings in the array and return an array without empty strings. It's convenient and simple. Let's analyze the parameters of the filter method callback function
//Let's take a look at the syntax of filter
var r = Array.filter(function(ele,index,_this){
console.log(ele);
console.log(index);
console.log(_this);
return ture;
})
/*
It can be seen that the key to using filter() as a high-order function is to correctly implement a filter function
Callback function: the callback function received by filter() can have multiple parameters. Usually we only use the first parameter to represent an element of Array, and the callback function can receive two other parameters to represent the location of the element and the Array itself.
*/
The most common use in business is to use filter to remove the repeated elements in the array
var r,arr = [1,1,3,4,5,3,4];
r= arr.filter(function(ele,index,self){
return self.indexOf(ele) === index;
})
console.log(r)
This allows us to quickly wait for an array without repeating elements. This is also a kind of weightlessness that we often encounter, and also a kind of interview.
4. sort() method
1. Definition: sort() method is used to sort the elements of the array and return the array.
2. Syntax format: arrayObject.sort(sortby);
3. Note: the sortby parameter is optional to specify the order of sorting, but it must be a function.
//Let's take a look at how to sort
//Sort from small to large, output: [1,2,3,9,56,87]
var arr = [9,87,56,1,3,2];
arr.sort(function(x,y){
if(x < y){
return -1
}
if(x > y){
return 1
}
return 0;
})
//If we want to sort in reverse order, we can put the big ones first [5,4,3,2,1]
var arr = [1,2,3,4,5];
arr.sort(function(x , y){
if(x < y ){
return 1
}
if(x > y){
return -1
}
return 0
})
//For example, if we want to sort a string, we can also sort it by the first character of the string, according to the size of ASCII
//For comparison, case letters ['good','apple','moide '] are ignored
var arr = ['good','apple','moide'];
arr.sort(function(s1,s2){
var x1 = s1.toUpperCase();//Turn capitalization
var x2 = s2.toUpperCase();
if(x1 < x2){
return -1
}
if(x1 > x2){
return 1
}
return 0
})
//To ignore case is to change the value to uppercase or all lowercase, and then make a comparison
//Note: the sort() method will directly modify the original Array, and the returned result is still the current Array
//And often we will see a lot of array objects in the code, and how to sort them relative to a certain attribute of the array object
//Here is an example of sorting array objects
var arr = [
{
Name:'zopp',
Age:10
},
{
Name:'god',
Age:1,
},
{
Name:'ytt',
Age:18
}
];
//A simple way of writing; default ascending order
function compare(prototype){
return function(a,b){
var value1 = a[prototype];
Var value2 = b[prototype];
return value1 - value2
}
}
//In general, we usually write a function of parameter function separately; it is clear and changeable
console.log(arr.sort(compare("Age")));
/*In the end, we have written so many examples and found that as variable partial parameter functions, there are two kinds of functions: one is ascending and the other is descending. In fact, we can also encapsulate the variable parameter function into a method, and use the method of parameter passing to indicate whether we want to ascending or descending order
*/
/**The method of sorting an array according to a property value in an array object
* Use example: newArray.sort(sortBy(type,rev,[,key]))
* @param type Represents the type of newArray, 'number' represents a numerical array [1,2], 'string' represents a string array ['abhs',' as'], 'obj' represents an object array [{}, {}]. If it is obj, the third parameter is required
* @param rev true Indicates ascending sort, false descending sort
* @param key The third function, which is not required, is passed as an attribute if the type is obj
* */
var sortBy = function(type,rev,key){
//The second parameter is not passed, and the default is ascending arrangement
if(!rev){
rev = 1
}else{
rev = rev ? 1 : -1;
}
return function(a,b){
//If it's string, we need to deal with unified uppercase or lowercase
if(type == 'string'){
a = a.toUpperCase();
b = b.toUpperCase();
}
//If it's obj, we take the corresponding attribute value
if(type == 'obj'){
a = a[key];
b = b[key];
}
if(a < b){
return rev * -1;
}
if(a > b){
return rev * 1;
}
return 0;
}
}
//This is the last unified encapsulation we want. You can also modify it yourself. This encapsulation is the last anonymous function to be processed, which is also one of the higher-order functions. We will also mention it later
Summary:
- If you want to get the results you want, whether ascending or descending, you need to provide a comparison function. This function compares the sizes of two values and then returns a number that describes the relative order of the two values.
- The comparison function should have two parameters a and b with the following return values:
- If a is less than b, that is, a - b is less than zero, a value less than zero is returned, and the array is arranged in ascending order.
- If a equals b, 0 is returned.
- If a is greater than b, that is, a - b is greater than zero, a value greater than zero is returned, and the array is arranged in descending order.