The first parameter of setTimeout is to execute the function immediately, I can’t understand it
for (var i = 0; i < 5; i++) {
setTimeout((function(i) {
console.log(i);
})(i), i * 1000);
}
Although the result is 0,1,2,3,4 is output immediately, but I don’t know why
In this way, everything is printed out at once. . . It's not printed every second. . It is recommended to write like this. .
Let me explain why 0, 1, 2, 3, 4 can be obtained.
There are many articles about JS pre-interpretation on the Internet. When entering the execution context stage, the function will not be executed. Simply put, when When you declare this function, it will not be executed as long as it is not called. Only a reference to this function will be saved in the context. It can be seen that this function is saved in memory. The function will only be executed when it is called. Let me talk about myself understanding, please point out if there is something wrong.
If the function is not executed immediately:
You are actually defining 5 timers in the for loop, but js is single-threaded, and these five functions will be placed in the queue to wait for execution. Here is an example that may not be appropriate. , you save these five functions function() {console.log(i);} as strings in the memory, and nothing happens until the five function calls are executed (which is the second parameter of setTimeout When the time is up), the function will start to be executed, because there is an i in the function. At this time, the i will be searched through the scope chain, and finally i is found in the outside scope, but at this time the for loop has already been executed. It's over, i has become 4, so five 4's will be printed.
If there is an immediate execution function (such as the one I wrote above):
You are actually equivalent to defining 5 timers in the for loop, But js is single-threaded, and these five functions will be placed in the queue waiting for execution.
But since the function outside is executed immediately, it will be executed immediately, and i is passed in. When these five functions are executed, i is searched upwards, and i is found in the scope of the immediately called function. So it will print out 0, 1, 2, 3, 4.
You first look at the brackets that enclose the entire function
That is:
The understanding of this paragraph is to wrap yourself into a package, a whole, and this whole is a function
So how to call the function next? Is the function name () like this? Add parentheses after the function name, and you can pass parameters into it
So naturally, this is what happened:
This kind of call is to write a function, wrap it with (), follow it with (), write the parameters in it, and execute it directly
As mentioned above, it prints out immediately, but your setTimeout has no effect at all.
The reason is that there is no return value after the immediate execution function is executed, so it is equivalent to setTimeout(undefined, i*1000).
setTimeout
requires the first parameter to be a function, so that after the time specified by the second parameter is up, the function defined by the first parameter will start to be executed.When you write:
You will notice that the timer is already working, but it will print out an
undefined
every 1 second. Because when this function is executed, i has jumped out of the loop and has no value.So you change it to this:
But in this case, the first parameter is not a function, but an expression, which means that the function will be executed immediately. It will not wait until the timer takes effect, but will be executed as soon as it is encountered. Execution, so the form of expression is to directly type 0, 1, 2, 3, 4.
Change it to this according to the statement above:
Although the first parameter is an expression, it will still be executed immediately, but the result of the execution of this expression is not to output a value, but to return a function. This satisfies setTimeout's requirement that the first parameter be a function, and gives The correct input parameters are set, so a correct result will be output every 1 second.
However, for the sake of team collaboration, I generally don’t recommend writing like this. I suggest you follow the standard writing method of setTimeout and write it like this:
This will at least make it easier for other members of the group to read and understand.
Because it is a function that is executed immediately, of course it is output immediately
For function scope issues, just change the point of this.
If the function is not executed immediately, five 5s will be printed, and they will be printed every one second, because the function in setTimeout will not be executed until the loop is completed. At this time, the global variable i is 5. Using the immediate execution function, each i in the loop will be obtained. There is a closure effect here. This i is now a local variable and exists in this function. The value of variable i is different every time it is executed.
The statement is executed immediately. This is
0 1 2 3 4
However, this has no return value, so the default is
undefined
So your code can be thought of like this:
Understand the principles, closure, stack, event queue, synchronization, asynchronous
Reverse the idea: remove the parameter i passed in and see if it can print normally. If not, analyze why
Can you change the writing methods to achieve the same effect as above? Analyze why
After completing the above points, you will know the reason, process and result