preface

In the course of learning JavaScript, we are likely to be exposed to higher-order functions more or less. So, do we have a clear definition of this, or very skilled grasp of these usages

If there are flaws and mistakes in the article, please also see the small partners to give advice, thank you in advance

The following left

Simply put, a higher-order function is a function that takes a function as an argument or returns a function as an output

What functions come to mind when you look at this concept

In fact, we often use some array methods, such as: map, filter and so on are the category of higher order functions

Of course, these JavaScript built-in methods are beyond the scope of this article, but here are some higher-order uses of functions that you might encounter in your actual development or interview process

Image stabilization

If a task is triggered frequently, the task is executed only when the interval between triggering the task exceeds the specified interval

The way to do this is if the task is triggered less often than the time we set, then we clear the previous task and start the timer again

function debounce(fn, interval) {
    let timer = null
    return function() {
        // If the user triggers it again within the specified time, it will be cleared
        clearTimeout(timer)
        timer = setTimeout((a)= > {
            fn.apply(this.arguments) }, interval); }}Copy the code

The throttle

Only one task is executed in the specified interval

function throttle(fn, interval) {
    let timer,
        firstTime = true // Whether this is the first execution
    return function () {
        let _this = this
        if (firstTime) {
            fn.apply(_this, arguments) // No delay is required the first time
            return firstTime = false
        }
        if (timer) { // If the timer is still indicating that the previous execution was not complete
            return false
        }
        timer = setTimeout((a)= > {
            clearTimeout(timer)
            timer = null
            fn.apply(_this, arguments)
        }, interval || 500); }}// Add a throttle valve without considering the timer
function throttle(fn, interval) {
    let canRun = true / / throttle valve
    return function() {
        if(! canRun) {return
        }
        canRun = false
        setTimeout((a)= > {
            fn.apply(this.arguments)
            canRun = true}, interval); }}Copy the code

Whether it is shaking or throttling, we can use the following way to verify

window.onresize = throttle(function () {
    console.log(1)},1000)
Copy the code

By the above two ways to achieve, believe that friends also understand the so-called tremble and throttling we are using setTimeOut to achieve, the different place is the location of the clear timer

The inertia function

When we need to reuse a logic, optimize the logic judgment to improve JavaScript performance

Principle: Functions of the same name are covered

function createXHR() {
    var xhr
    try {
        xhr = new XMLHttpRequest()
    } catch (e) {
        handleErr(e)
        try {
            xhr = new ActiveXObject('Msxml2.XMLHTTP')}catch (e) {
            try {
                xhr = new ActiveXObject('Microsoft.XMLHTTP')}catch (e) {
                xhr = null}}}return xhr
}

function handleErr(e) {
    // do sth
}
Copy the code

Modified version of lazy function:

function createXHR() {
    var xhr
    if(typeofXMLHttpRequest ! = ='undefined') {
        xhr = new XMLHttpRequest()
        createXHR = function() {
            return new XMLHttpRequest()
        } 
    } else {
        try {
            xhr = new ActiveXObject('Msxml2.XMLHTTP')
            createXHR = function() {
                return new ActiveXObject('Msxml2.XMLHTTP')}}catch(e) {
            try {
                xhr = new ActiveXObject('Microsoft.XMLHTTP')
                createXHR = function() {
                    return new ActiveXObject('Microsoft.XMLHTTP')}}catch(e) {
                createXHR = function() {
                    return null}}}}return xhr
}
Copy the code

After the above modification, when we call this function for the first time, we will judge the current environment, and then abbreviate the function optimization, without further judgment

For example, the XMLHTTPRequest in the above code, if it exists, is already there when we call the function the second time

function createXHR() {
    return new XMLHttpRequest()
}
Copy the code

Usage scenario:

  • Use the same judgment logic frequently
  • Only need to judge once, the subsequent use of the environment is stable

Cascade function

It’s a chain call, so the principle is simple: return the object itself in each method

Suppose we have a Person template

function Person() {}
// Add several methods
Person.prototype = {
    setName: function (name) {
        this.name = name
        return this //
    },
    setAge: function (age) {
        this.age = age
        return this
    },
    setSex: function (sex) {
        this.sex = sex
    },
}
// Don't forget to respecify the constructor
Person.constructor = Person
let person = new Person()
// This seems to be doing a lot of repetition. modify it a little bit and put this return in each method to achieve the effect of chained calls
person.setName('Wandering de Tadpole')
person.setAge(18)
person.setSex('male')
// After the modification
person.setName('Wandering de Tadpole').setAge(18).setSex('male')
console.log(person)
Copy the code

Advantage: Simplifies the steps of the function call, we don’t have to write something repetitive

Disadvantages: Occupies the return value of the function

Currie,

The parameters are collected and executed later, also known as partial evaluation

function add(a, b) {
    return a + b
}

// Simple generic encapsulation
function curry(fn) {
    let args = Array.prototype.slice.call(arguments.1)
    return function() {
        let _args = Array.prototype.slice.call(arguments)
        let final = args.concat(_args)
        return fn.apply(null, final)
    }
}

// Add curlize the function
let adder = curry(add)
adder(1.2)
/ / or
let adder = curry(add, 1) (2)
let adder = curry(add)(1.2)
Copy the code

A typical generic curry encapsulation

Function.prototype.mybind = function(fn) {
    let args = Array.prototype.slice(arguments.1)
    let _this = this
    return function() {
        let _args = Array.prototype.slice(arguments)
        let final = args.concat(_args)
        return _this.apply(fn, final)
    }
}
Copy the code

With this pattern of curry functions, we can implement a simple bind

Function.prototype.mybind = function(fn) {
    let _this = this
    return function() {
        return _this.apply(fn, arguments)}}Copy the code

Function currying is also a problem we may often encounter in the interview process, such as:

// Write an add function that implements the following functions
add(1) (2) (3) / / 6
add(1) (2.3) (4) / / 10
add(1.2) (3) (4.5) / / 15

function add() {
    let args = Array.prototype.slice.call(arguments)
    let adder =  function() {
        // Use the closure feature to save args and collect parameters
        args = args.concat(Array.prototype.slice.call(arguments))
        return adder
    }
    // Return the final calculated value using the properties of toString implicit conversions
    adder.toString = function() {
        return args.reduce((a, b) = > {
            return a + b
        })
    }
    return adder
}
add(1) (2) (3) / / 6
add(1) (2.3) (4) / / 10
add(1.2) (3) (4.5) / / 15

// Of course, we can use ES6 method to simplify this function
function add1(. args) {
    let adder = (. _args) = > {
        args = [...args, ..._args]
        return adder
    }
    adder.toString = (a)= > args.reduce((a, b) = > a + b)
    return adder
}
Copy the code

To achieve the effect of the above function, I think there are two things we need to understand and understand:

  • Closures, which use the closure feature to save and collect the parameters we need
  • usingtoStringTo get the result we want

Afterword.

What’s your first impression after reading the above examples of higher-order uses of functions

Closure! Closures are one of the things we have to conquer to be a proper front end

If you are interested, you can click here or scan the qr code below to follow my wechat official account and see more front end snippets. Welcome to star