“This is the fifth day of my participation in the First Challenge 2022. For details: First Challenge 2022”
What is a closure
The beginning is clear, concept first. What closures are and why js is full of closures.
A closure is a function that has access to a variable in the scope of another function. This function and the referenced variable together make up the closure
The text description is so hard to understand that it makes sense when you look at the code
function test() {
var a = 1
var b = function() {
console.log(a)
}
return b
}
Copy the code
In the above code example, variable A is in the scope of function test, but variable A is accessible from function B. To apply the concept of a closure, function B has access to variable A in function test’s scope, so that function B and variable A form a closure.
After looking at the example above, it suddenly dawned on you that this is what we always write in code. So JS is full of closures.
How do I observe closures
How do we know if we’ve written a closure in our code if we don’t know a lot about closures in the first place? Here’s how to find closures
function test() {
let a = 1
return function test1() {
debugger
console.log(a)
}
}
test()()
Copy the code
In the code above, after executing the debugger keyword, we can open the browser’s developer modulation tool and see the Closure in the call stack. This means that we have written a Closure
The misperception of closures
Now that I’ve talked about closures, let’s talk about some of the misconceptions you might have about closures.
1. Closures need to be exposed using return
First of all, in terms of the concept of closures, it is not said that closures need to be exposed to the function to be a closure, but that they are generated by referring to variables that are not in the scope of the current function.
Why is there such a misunderstanding, because we use closures quotes outside the scope of variables, the general is to expose the variable, or is the function to go out, let us in the external can also access to the variable or function, that is to say, the closure exposed to the external function is just our business needs, rather than a necessary for closure.
2. Closures cause memory leaks
First of all, we want to know why the closure can cause memory leaks, because we will be the closure when exposed to the external function, the closure inside still refer to the outer scope of variables, lead to external scope variables cannot be recycled garbage collection mechanism, if the circular reference closure is likely to cause a memory leak phenomenon. But this is due to the process of using closures, not the nature of the closures themselves, so it is not prudent to say that closures always cause memory leaks. (In addition, the browser garbage collection mechanism has been optimized since Internet Explorer 9, which is now less likely to cause memory leaks.)
Closures cause problems
Loop traps, one of the eight traps in JS, are caused by closures
for (var i = 0; i < 4; i++) {
setTimeout(() = > {
console.log(i)
}, 1000)}// 4, 4, 4, 4
Copy the code
The callback function in setTimeout is a closure that refers to the variable I in the outer scope, but there is only one I. It does not generate a new I in each callback. So when you print after 1s, you’re accessing the I variable in the same scope, so you’re printing four fours
There are two ways to solve these problems:
- One is using ES6
let
The syntax generates block-level scopes so that the I variables in each block-level scope do not refer to the same I variable and do not affect each other
for (let i = 0; i < 4; i++) {
setTimeout(() = > {
console.log(i)
}, 1000)}// 0, 1, 2, 3
Copy the code
- One is to use immediate-execute functions, where the variable I in each immediate-execute function is a snapshot of the current external variable I
for (let i = 0; i < 4; i++) {
(function(i) {
setTimeout(() = > {
console.log(i)
}, 1000)
})(i)
} // 0, 1, 2, 3
Copy the code
Closure usage scenarios
With all this talk about the nature of closures, and even the fact that closures can cause such a big problem as loop traps, what are closures really good for? When asked, you can’t say js is everywhere closure, so js is everywhere closure usage scenarios. So let’s talk about some of the classic use scenarios for closures
1. Singleton mode
var CreateSingleton = (function() {
var instance = null
var CreateSingleton = function() {
if (instance) return instance
return instance = this
}
return CreateSingleton
})()
Copy the code
The singleton pattern is a type of design pattern designed to ensure that there is only one instance object globally. The code above creates a closure using instance. The singleton pattern is particularly useful for ensuring that there is only one popover component globally in the component library.
2. Coriolization of functions
Function test(a, b, c) => function test(a)(b)(c)
function currying(Fn, args) {
var _this = this
var len = fn.length
var args = args || []
return function() {
var _args = Array.prototype.slice.call(arguments)
Array.prototype.push.apply(args, _args)
if(_args.length < len) {
return currying.call(this, fn, _args)
}
return fn.apply(this, _args)
}
}
Copy the code
3. Use it in conjunction with immediate execution functions to complete the encapsulation of the class library
Closures are often used in conjunction with instant-execution functions and can be powerful. As a result, many people are often misled into thinking that a closure has anything to do with an immediately executing function, or even that an immediately executing function is a closure. This is wrong, however, because executing functions immediately has nothing to do with closures.
In the era of jQuery, the umD specification is compatible with many different environments, mainly because of the implementation of the UMD header structure
(function( global, factory ) {
"use strict";
if ( typeof module= = ="object" && typeof module.exports === "object" ) {
module.exports = global.document ?
factory( global.true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}
})( typeof window! = ="undefined" ? window : this.function( window, noGlobal ) {})
Copy the code
The above code should be familiar to anyone who has used jQuery development.
4. Save private variables
In real development, we sometimes need to cache the results of a calculation, or to keep private variables from being accessed externally. This can be done using closures.
In addition, the two popular front-end frameworks Vue and React also use a large number of closures for the implementation of related functions, you can check the source code
The above is my superficial understanding of closures, I hope you can criticize and correct.