Closures and immediate function applications
A closure
Closures have been defined and explained in this article, including how to implement a closure. For details, see the previous section.
The core role of closures is to privatize variables and prevent external access.
Execute the function immediately
The immediate execution Function is IIFE (Immediately-Invoked Function Expressions).
As the name implies, it is executed as soon as it is defined. The special feature of an immediate function is that it takes no life and executes immediately when it is defined. It is immediately destroyed after execution and does not occupy memory.
Closure and immediate function applications
Let’s talk about the use of immediate functions, how they work with closures, and what they can achieve.
1. Scenario 1
Count for a variable number, every one second +1, and print the number
Under normal circumstances, we might write something like this:
var number = 0 setInterval(function () { console.log(++number) // 1 2 3 4 5 6 7 8 9 10 ... }, 1000).Copy the code
This is fine, but when number is exposed globally, we can “hide” number as a temporary variable by executing the function immediately.
setInterval((function () {
var number = 0
return function () {
console.log(++number) // 1 2 3 4 5 6 7 8 9 10 ...
}
})(), 1000)
Copy the code
If you look closely at this part of the code, the function he’s actually executing in the timer is still
The function in parentheses is passed to the timer in the form of a return from the immediately executing function. In this way, number is wrapped inside the timer by the immediate function and is not accessible outside the timer.
2. Scenario 2
Construct a function that returns an array whose ith element is a function that prints I.
function getLogsArray () {
var arr = []
for (var i = 0 ; i < 100 ; i++) {
arr[i] = function () {
console.log(i)
}
}
return arr
}
const logger = getLogsArray()
logger[1]() // 100
logger[2]() // 100
logger[50]() // 100
Copy the code
This is clearly the wrong result and not the desired result
Logger [1]() should print 1 instead of 100
The cause of this result must be the scope of the problem, in fact we found that the recycling of the I through var to declare, so the scope of the I got a raise, I called the entire function scope under the only variable values, i.e. array inside all I point to the current scope an I, when the loop execution after, I becomes 100, so whatever element in the entire array is going to print 100.
How to solve this problem? The easiest way to do this is to change the var keyword to the let keyword, so that the scope of I only exists in the loop, and each loop is a new variable, so that the I printed in the array is different.
function getLogsArray () {
var arr = []
for (let i = 0 ; i < 100 ; i++) { // cahnge var to let
arr[i] = function () {
console.log(i)
}
}
return arr
}
const logger = getLogsArray()
logger[1]() // 1
logger[2]() // 2
logger[50]() // 50
Copy the code
Another solution, which is the focus of the moment, is to use immediate execution functions.
function getLogArray () {
var arr = []
for (var index = 0 ; index < 10; index++) {
(function (i) {
arr[i] = function () {
console.log(i)
}
})(index)
}
return arr
}
const loggerArray = getLogArray()
loggerArray[1]() // 1
loggerArray[2]() // 2
loggerArray[50]() // 50
Copy the code
In the function, the value of I is changed, but we can set the print method to a separate scope by taking an argument from the immediate-execute function and accepting the index parameter. In the print method, I is the independent argument in the immediate-execute function. No matter how index is edged, it does not affect printing.
Four:
Executing functions immediately does not end up creating and saving new variables, and working with closures can create separate scopes for closures.