3 ms·
That's why Javascript introduced the "let" keyword years ago This logs from 0 to 9: for(let i = 0; i < 10; ++i;) setTimeout(() => console.log(i)); This logs
by sakex 2y ago
That's why Javascript introduced the "let" keyword years ago
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));
- NwtnsMthd 2y agoDo you think you could elaborate on why the results differ? I'm somewhat unfamiliar with how JavaScript works.
- wging 2y ago'var' is JavaScript's older variable declaration construct. Variables created this way are live from the beginning of the function that contains them (or globally if there isn't one). So a block with braces (such as you'd use for a for or while loop body) doesn't actually restrict the scope of var `v` below: 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/Reference/Statements/for#lexical_declarations_in_the_initialization_block 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/Reference/Statements/let https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- wging 2y agoFun(?) fact: it's not technically true that const can't be used in for loops: 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'); }
- mst 2y agoYep, with exactly the same semantics as perl5's 25+ years old 'my' - 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 ;).