High Order Function: A function Accepts functions as parameters and/or Returns a function.

Extending the function which is not changed.

We have a function named sayHi.

function sayHi(...args) {
    console.log('hi', ...args)
}

sayHi('Jerry')

How we can do, If we want to do something before sayHi is called.

 const newSayHi = sayHi.before(() => {
     console.log('this is called before sayHi')
})

  newSayHi('Tom')

Now, let's implement the sayHi.before.

sayHi.before = function(cb) {
    return (...args) => {
        cb()
        this(...args)
    }
}

Now we can extend a function that is not changed.

Currying - Fixed the parameter.

Currying is one type of high order functions. Currying is an advanced technique of working with functions.

We can fix the parameter by implementing a Currying function.

Let us implement a simple function which can judge the value is the specific type or not.

function isType(val, type) {
    return Object.prototype.toString.call(val) === `[object ${type}]`
}

console.log(isType('hello', 'String')) 
console.log(isType(123, 'Number'))
console.log(isType(123, 'number'))
console.log(isType(123, 'String'))

However, it's easy to make a spelling mistake about type, like numbernmuber and there are not code hints.
So we want to fix the type parameter, like below.

const isString = isType2('String')

console.log(isString('hi'))
console.log(isString(456))

Now let us implement isType2.

function isType2(type) {
    return (val) => {
        return Object.prototype.toString.call(val) === `[object ${type}]`
    }
}

In conclusion, higher order functions are a very powerful way of programming.

code: https://github.com/Terence-Cheng/Frontend_Blog/blob/main/Javascript/HighOrderFunctions/index.js