Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

JavaScript for — Loops are… complicated — HTTP203 Thanks Jake and Surma for sharing JavaScript for — Loops are… complicated — HTTP203.

for (var i = 0; i < 2; i++) {
    console.log(i)
}
Copy the code

Today’s sharing is a bit of a guessing game. Today I want to talk about how the loop system (FOR) actually works in the engine. On the face of it, the for loop has three instructions, initialize, condition, and multiplicator. First initialize I once, then determine if I satisfies the condition I < 2 and exit if it satisfies the condition, then run the body of the loop, console.log(I) and then run I ++, and then return to the condition. The answer is obvious

0
1
Copy the code

You might look at this and wonder if this is too easy, which means you’re going home empty-handed today. Because loops are really, really simple. Let’s take a look at one that’s a little difficult, but one that a front-end programmer with a little experience can blurt out and give the right answer.

for (var i = 0; i < 2; i++) {
    setTimeout(() = >console.log(i))
}
Copy the code

SetTimeout Specifies a minimum delay of 4 milliseconds by default. We hide the print in a closure so you can think about it and give an answer, and sometimes just because we can give an answer doesn’t mean you really understand it.

First of all, there’s only one I and if there’s a parent function I is the parent function, and if there’s not it’s the global function, so when console.log, I has changed to 2 to print 2 twice, and I need to figure out why it’s print 2 twice, why it’s print 2 both times.

We should give you the answer soon, but it’s not complete yet

for (let i = 0; i < 2; i++) {
    setTimeout(() = >console.log(i),0)}Copy the code

The innerConst declared in the block scope should raise the ReferenceError: innerConst is not defined.

if(true) {var innerVar = 1;
    const innerConst = 1;
    let innerLet = 1;
}

console.log(innerVar);
console.log(innerConst);//ReferenceError: innerConst is not defined
console.log(innerLet);//innerLet is not defined
Copy the code

In the example above, we have noticed that the variables declared by the let are geographically limited, that is, they have a range of activities, that is, their life cycle is geographically limited. However, in the example above for loop, this experience does not make sense.

The ECMAScript specification actually handles this situation in a special way. The let statement appears to work outside of the for block, which looks magical.

Each iteration creates a lexical scope. So it’s actually a new I variable, not just assigning a new value to the same variable, but a new variable.

let i = 0
i < 2
setTimeout(console.log(i))
i++;
Copy the code

Usually we think of it as each iteration and this is the order, but it’s not.

for (let i = 0; i < 2; i++) {
    setTimeout(() = >console.log(i))\\1
    i++;
}
Copy the code

If setTimeout(()=>console.log(I)) is run, it will print 0, but instead of 0, it will print 1. That’s the weird thing. The increment i++ runs at the beginning of every iteration except the first.

Here we create the variable let I = 0 and we create a new lexical environment to which we copy the value of I before the condition is judged. And then now I = 0 and then the I ++ statement will be updated to 1, next iteration. It works a lot like VAR. But it’s doing a lot of leaping work,

for (const i = 0; i < 3; i++) {
    setTimeout(() = >console.log(i))
    i++;
}
Copy the code
TypeError: Assignment to constant variable.
Copy the code