Definition of closure
Closures are functions that can read variables inside other functions.
In javascript, for example, local variables can only be read by child functions inside a function, so closures can be understood as “functions defined inside a function.”
In essence, closures are Bridges that connect the inside and outside of a function.
Why use closures
Let’s start with the pros and cons of global versus local variables
Global variables: They can be reused, but are globally dirty and easy to tamper with.
Local variables: They are used only within functions without global contamination, tampering, and reuse.
Therefore, global and local variables have opposite advantages and disadvantages. The advent of closures combines the advantages of global and local variables.
When to use closures
When you want to reuse an object but protect it from contamination and tampering.
Why closures occur
Official explanation:
A closure is an expression (usually a function) that has many variables and the environment to which they are bound, and thus these variables are part of that expression.
From this we can see that closures are related to the environment, and the relationship with the environment is inseparable from the scope. However, the special aspect of the JS scope is the lexical scope, which is also called static scope or closure.
A static scope is a scope that is defined when a function is declared and will not change.
The language features of JS have already fixed everything while JS code is running. The scope and everything are fixed, and closures are created accordingly.
Closure is a feature of JS language. Closure is usually a function. Function is an independent scope. Enclosing its lexical scope, functions have many special forms of functions, which makes packages. The package is different, but it can refer to a member variable of an external function, which must be the package.
If you can refer to a member variable of an external function, it must be a closure.
Here is a detailed illustration of closures
The representation of closures
- Return a function
- Passed as a function parameter
- The callback function
- Atypical closures
IIFE
(Execute function expression immediately)
Return a function: Closures of this form are very, very common in JS.
var a = 1;
function foo(){ var a = 2; // This is the closurereturn function(){ console.log(a); } } var bar = foo(); // Output 2 instead of 1 bar();Copy the code
Passed as a function parameter: No matter how an inner function is passed outside its lexical scope, it holds a reference to the original scope and generates a closure no matter where the function is executed.
var a=1;
function foo(){
var a=2;
function baz(){
console.log(a);
}
bar(baz);
}
functionBar (fn){// This is the closure fn(); } // Print 2 instead of 1 foo();Copy the code
Callbacks: Whenever you use callbacks in timers, event listeners, Ajax requests, cross-window communication, Web Workers, or any asynchrony, you’re actually using a closure
/ / timersetTimeout(function timeHandler(){
console.log('timer'); },100)'#container').click(function(){
console.log('DOM Listener');
})
Copy the code
IIFE:IIFE(execute function expressions immediately) is not a typical closure, but it does create one.
var a = 2;
(function IIFE(){// output 2 console.log(a); }) ();Copy the code
How to solve the following loop output problem
for(var i = 1; i <= 5; i ++){
setTimeout(function timer(){console.log(I)}, 0)} How can I improve it so that it prints 1,2,3,4,5? (The more ways, the better)Copy the code
The code analysis
The for loop creates five timers and starts executing after the loop ends
After the for loop, the variable I defined by var I is now equal to 6
Five timers in turn print the variable I, so the result is 5 6 prints
** First improvement: ** Uses IIFE (execute function expression immediately) to pass the I variable to the timer each time for loop
for(var i=1; i<=5; i++){ (function(j){
setTimeout(function timer(){
console.log(j)
},0)
})(i)
}
Copy the code
The second improvement: the third argument to the setTimeout function can be used as a variable when the timer is executed
for(var i=1; i<=5; i++){setTimeout(function timer(j){
console.log(j)
}, 0, i)
}
Copy the code
Third improvement (recommended) : use let I instead of var I in loops
for(leti=1; i<=5; i++){setTimeout(function timer(){
console.log(i)
}, 0)
}
Copy the code