javascript - The first parameter of setTimeout is to execute the function immediately, I can't understand it
大家讲道理
大家讲道理 2017-07-05 10:56:26
0
9
1010

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

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

reply all(9)
给我你的怀抱

In this way, everything is printed out at once. . . It's not printed every second. . It is recommended to write like this. .

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    return function() {
        console.log(i);
    }
  })(i), i * 1000);
}

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.

(function(i) {

return function() {
    console.log(i);
}    

})(i)

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:

(function (i) {
      console.log(i);
})

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:

(function (i) {
    console.log(i);
})(i)

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:

for (var i = 0; i < 5; i++) {
  setTimeout(function(i) {
    console.log(i);
  }, i * 1000);
}

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:

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    console.log(i);
  })(i), i * 1000);
}

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:

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    return function() {
        console.log(i);
    }
  })(i), i * 1000);
}

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:

var j = 0;
for (i = 0; i < 5; i++) {
  setTimeout(function() {
     console.log(j);
     j++;
  }, i * 1000);
}

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.

for (var i = 0; i < 5; i++) {
    setTimeout((function(i) {
        console.log(i);
    }).bind(this,i), i * 1000);
}
習慣沉默

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.

黄舟
(function(i) {
    console.log(i);
})(i)

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:

for (var i = 0; i < 5; i++) {
  var temp = (function(i) {
    console.log(i);
  })(i); 
  // temp 是 undefined 
  setTimeout(temp, i * 1000);
}

黄舟
  • 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

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template