“This is the 25th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Writing in the front

Higher-order functions, what a fancy name they sound, are not as unreachable as they sound.

This article will take you through higher order functions step by step.

What what what?

First, let’s explain what this higher-order function is:

  • Functions can be passed as arguments

  • The function can be output as a return value

Only one of the above conditions needs to be satisfied, and that is a higher-order function.

Pass the function as an argument

Passing functions as parameters means we can put some business logic in functions as parameters, separating the changing and unchanging parts of the business code.

One common usage scenario is the callback function.

The callback function

The use of callback functions is very common when using Ajax.

When we want to do something after we get an Ajax return, because we don’t know exactly when we will get the return, the common way to do something is to pass it into an Ajax request as a function, and execute the callback method after the request completes.

Watch a 🌰

var getUserInfo = function(id,cb){
    $.ajax('http://xxx.com/getUserInfo?' + userId,function(data){
        if(typeof cb === 'function'){
            cb(data)
        }
    })
}

getUserInfo(Awesome!.function(data){
    alert(data.userName)
})
Copy the code

In the example above, we can see that we pop up the user name we got after we got the Ajax request.

Callbacks are not just used in asynchrony. When certain operations are not suitable to be performed in a function, we can extract the operations into a function, pass this function as a parameter to another function, and delegate the execution to another function.

sort

Array.prototype.sort takes a function as an argument that encapsulates the sorting of Array elements.

From the use of the sort method, we can see that all we need to do is sort the array, which is fixed.

What has changed is the sorting rules. We have encapsulated this part in the function parameters and passed the sort method dynamically to make array.prototype. sort very flexible.

[1.4.3.2].sort(function(a,b){
       return a-b
}) // [1, 2, 3, 4]

[1.4.3.2].sort(function(a,b){
       return b-a
}) // [4, 3, 2, 1]
Copy the code

Function is output as the return value

Functional programming is more clever when functions are output as return values than when they are passed as arguments.

Determine the type of data

When we want to determine a data type, we split it into a function.

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 ){ 
    return Object.prototype.toString.call( obj ) === '[object Number]'; }; .Copy the code

getSingle

Let’s take an example of the singleton pattern.

var getSingle = function(fn){
    var ret 
    return function() {
        return ret || (ret = fn.apply(this.arguments))}}Copy the code

In this example, we both pass the function as an argument and have the function execute and return another function.

So let’s see what happens

var getScript = getSingle(function(){
    return document.createElement('script')})var script1 = getScript()
var script2 = getScript()

console.log(script1 === script2) // true script1 and script2 are created script tags
Copy the code

Higher order function implementationAOP

We need to start by explaining what AOP is: the main purpose of AOP is to isolate functionality unrelated to the core business logic module, also known as section-oriented programming.

After these functions are removed, they are dynamically woven into the business logic module to maintain the purity and high cohesion of the business logic module.

When implementing AOP in JS, we usually mean weaving one Function into another Function dynamically. Here’s an example of how to do this by extending function.prototype.

Function.prototype.before = function(beforefn){
    var that = this // Save a reference to the original function
    return function(){  // Returns a "proxy" function that contains both the original function and the new function
        beforefn.apply(this.arguments) // Execute a new function to fix this
        return that.apply(this.arguments) // Execute the original function}}Function.prototype.after = function(afterfn){
    var that = this
    return function(){
        var res = that.apply(this.arguments)
        afterfn.apply(this.arguments)
        return res
    }
}

var fun = function(){
    console.log(2)
}

fun = fun.before(function(){
    console.log(1)
}).after(function(){
    console.log(3)
})

fun()

/ / 1 2 3
Copy the code

This AOP approach to adding responsibilities to functions is also a particularly clever implementation of the decorator pattern in JS.

I’ll talk about the decorator model when I get a chance.

Other applications

This section describes some common application scenarios of higher-order functions.

Currie,

A quick introduction to Coriolization is that a Coriolization function takes some parameters. After receiving these parameters, the function does not execute immediately. Instead, it continues to return another function, storing the parameters in the closure formed by the function. When the function is actually asked for a value, all the arguments passed in before are used to evaluate it at once.

Let’s do an example to make it easier to understand

var address = (function(){
    let res = ' '
    return function(){
        for(let val of arguments){
            res += val
        }
        return res
    }
})()

var curring = function(fn){
    let args = []
    return function(){
        if(!arguments.length){
            return fn.apply(this,args)
        }else{
            args = [...args,...arguments]
            return arguments.callee
        }
    }
}


address = curring(address)

address('China')

address(Jiangsu Province)

address('Wuxi')

address()

// 'Wuxi, Jiangsu province, China'

Copy the code

This completes a Currification function for the input address, which, when called to address, will be temporarily stored if it takes parameters, and only when it does not, will the actual evaluation be performed.

The throttle

When some functions are called frequently in certain scenarios, it can cause significant performance problems.

For example, frequently clicking buttons to call interfaces, window.onresize, Scroll, etc.

When we fire these events frequently, we may only need to fire once in a certain period of time, which requires us to ignore some events by time period.

Code implementation:

function throttle(fun, wait) {
    let timeout = null;
    return function() {
      if(! timeout) {// If the timer does not exist
        timeout = setTimeout(function(){ // Set wait time to trigger
          timeout = null; // Clear the timer
          fun() // Execute method
        }, wait)
      }
    }
}

function test(){
  console.log('test')}// Let's use the browser scroll as an example
window.onscroll = throttle(test, 1000);
Copy the code

The last

Above, it is oneself to high order function some shallow understanding, welcome each big guy to clap brick.

Meanwhile, I would like to recommend a MD-style component library of VUE3 mobile terminal that I participated in. Welcome to star & PR