I’ve reading the MDN docs, and I can truly say this is the first time in a while I have been baffled.
Refer to this code:
for (
let i = 0, getI = () => i, incrementI = () => i++;
getI() < 3;
incrementI()
) {
console.log(i);
}
// Logs 0, 0, 0
I see the 1st iteration:
- for loop initializes
i
to0
- creates a closure over
i
- creates a closure over
i++
- calls
getI
function and returns0
, executes the condition to continue, the loop executesconsole.log(i)
- Is a new lexical scope created after
console.log(i)
? Does the initiali
variable disappear? - does
getI
function get defined for each new iteration?
- Is a new lexical scope created after
- calls
incrementI
and performsi++
- Is a new
i
variable created, the previousi
copied to the newi
and then the newi
incremented?
- Is a new
- next iteration begins
- If a new
i
is generated with the new incremented value, why doesconsole.log(i)
still refer to the initiali
, which is 0?
- If a new
I read the documentation in MDN about for
, however I could not find explanation of the behaviour shown in the code snippet. Why does it log 0
, 0
, 0
instead of 0
, 1
, 2
?
2
Answers
I you want make that function work, just put initialization of
i
outsidefor
.The answer lies in this part of the docs
Ie, after each iteration of the loop a new
i
is declared with the value of the previous one. Then theafterthought
is evaluated. But as in your case,getI
andincrementI
are closed over the originali
this originali
is incremented and checked (so the loop eventually stops) but the next call toconsole.log
always uses the "new"i
, which is initialized to0
(ie the value of in the previous iteration before the afterthought was evaluated) and then never incremented.