My knowledge of javascript semantics is pretty limited, but you can see what's happening more clearly:
for (let i = 0; i < 10; ) {
setTimeout(() => {
console.log(i, foo);
}, 1000);
let foo = "baz-"+i;
i++;
}
// "1 baz-0", "2 baz-1, etc
It's behaving as each loop iteration is creating its own closure, and the inner function is referring to those variables by reference. So any changes you make to them inside the body of the loop will end up visible to the inner function.
My point is that for the i++ to make the loop advance (whether it is written inside the block or outside it in the header), behind the scenes, the value of the old i is copied to the new i at the beginning of each iteration.
I think to then understand why my two examples produce different results, you have to know that the i++ in the header happens to be executed after that copying has been made (an arbitrary choice?), while the i++ within the body will be (naturally) executed before the copying.
I suppose the way it works can be intuitive, but it can also be confusing if you think of the i++ as the last action of each iteration in both of my example cases.
Actually, there's a third way to write the example loop, but who can guess which result it gives?
for (let i = 0; i++ < 10; ) {
setTimeout(() => {
console.log(i);
}, 1000);
}
... it will print 1...10! So even within the loop header, one part is run before the copying and another part after the copying. How is this intuitive and where is this documented apart from the language spec?
EDIT: My bad, of course the iteration condition has to be checked at the beginning of the iteration, so in this third example i == 1 during all of the first iteration).
There we can finally see that on the first iteration, an environment is created (and iteration variables copied) before the test ("step 2"). After that, a new environment is created (and iteration variables copied) towards the end of each iteration, before the increment step ("step 3.e" and "step 3.f").
Another commenter links to a great video that explains the same thing about the spec and how confusing the environment creations can be: https://news.ycombinator.com/item?id=33160373