← Back to context

Comment by NwtnsMthd

12 days ago

Do you think you could elaborate on why the results differ? I'm somewhat unfamiliar with how JavaScript works.

'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/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...

  • Fun(?) 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');
        }