This logs from 0 to 9:
for(let i = 0; i < 10; ++i;) setTimeout(() => console.log(i));
This logs from 10, 10 times: for(var i = 0; i < 10; ++i;) setTimeout(() => console.log(i));
This logs from 0 to 9:
for(let i = 0; i < 10; ++i;) setTimeout(() => console.log(i));
This logs from 10, 10 times: for(var i = 0; i < 10; ++i;) setTimeout(() => console.log(i));
foreach my $x (@input) {
push @callbacks, sub { $x };
}
works how you'd expect.I was spoiled by this and driven nuts by function level scoping like python's and javascript's 'var', and the adoption of 'let' made me very happy.
My current annoyance with JS is its lack of -
my $foo = do {
...;
...;
<expression>
};
but there's a proposal for that, and the 'match' proposal (which would be glorious) depends on it on the basis it's a shoo-in, so I am very hopeful.Note that I know:
let foo; {
...;
...;
foo = <expression>
}
already works but it's Not The Same (although significantly less upsetting than (() => { ... })() is ;). console.log(v); // <-- v is a variable here, we can access its value even though it is only declared below
// prints 'undefined'
{
var v = 1;
console.log(v); // prints 1
}
console.log(v); // prints 1
You used to (and might still) see a workaround to recover more restrictive scoping, known as the "IIFE" (Immediately Evaluated Function Expression): (function () { var v; ... code using v here ... })() creates a function (and thus a more restrictive scope for v to live in) and evaluates it once; this is a sort of poor man's block scoping.`let` and `const` were created to fill this gap. They have block scope and are special-cased in for loops (well, `let` is; you can't reassign to a `const` variable so nontrivial for loops won't work):
console.log(l); // <-- throws ReferenceError: l is not defined
{
// pretend the console.log line above is commented out, so we can reach this line
let l = 1;
console.log(l); // prints 1, as expected
}
console.log(l); // throws ReferenceError: l is not defined
// ^^ l was only in scope for the block above
The interaction with `for` is explained well on MDN, including the special casing: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe..."More precisely, let declarations are special-cased by for loops..." (followed by a more detailed explanation of why)
See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
for (const i = 0; i > 0; ) {
console.log('this is stupid');
}
let ran = false;
for (const i = 0; !ran; ran = true) {
console.log('this is also stupid');
}