getify / You-Dont-Know-JS

A book series on JavaScript. @YDKJS on twitter.
Other
178.28k stars 33.42k forks source link

es6 & beyond/Syntax How many scopes will be created in for&let loop? #1683

Closed liquancss closed 4 years ago

liquancss commented 4 years ago

https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch2.md#let--for

The let i in the for header declares an i not just for the for loop itself, but it redeclares a new i for each iteration of the loop.

After reading this paragraph, a question occurs to me. How many scopes will be created in the for&let loop in the following code snippet. for(let i=0; i<3; i++){ console.log(i); }

From your words, it seems that "for(let i=0; i<3; i++)" will create only one scope for loop itself and the loop body will create a new scope for each iteration. So four scopes will be created in the for&let loop in that code snippet. Does it right? Or I mis something?

getify commented 4 years ago

Short answer: Both. Conceptually the answer is 3, technically, the answer is 4.


The intent of the sentence, with the "not just" part, is to assert that it's "not creating a scope for itself but for its iterations", not that "it's creating both a scope for itself and its iterations" -- though I concede "just" can be read to imply the latter.

Conceptually, it's cleaner to assert that only each iteration itself gets a scope, so 3 iterations means 3 scopes.

But technically, for this per-iteration scoping to still work, and yet the overall counting progress to be maintained across iterations, the loop needs a its own hidden outer scope to maintain that state, so basically a 4th scope is wrapped around the loop:

// so this...
for (let i = 0; i < 3; i++) {
   // ..
}

// technically behaves more like this...
{ let $i;
   for ($i = 0; $i < 3; $i++) {
      let i = $i;
      // ..
   }
}
liquancss commented 4 years ago

Many thanks for your kind explanation. I thought I've got it.