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
- using
toString
To 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