1

I have the following document https://www.codementor.io/cchilder/draft/bcgnrvw5p where I try to explain this:

// declare variables
const x = 1;
let y = 2;
var z = 3;

console.log(`Global scope - x, y, z: ${x}, ${y}, ${z}`);

if (true) {
    console.log(`A new block scope - x, y, z: ${x}, ${y}, ${z}`);

    // redeclare variables
    // const x = 4;
    let y = 5;
    var z = 6;
}

At the top of the if block, y is not defined:

$ node variables.js 
Global scope - x, y, z: 1, 2, 3
/Users/cchilders/variables.js:9
    console.log(`A new block scope - x, y, z: ${x}, ${y}, ${z}`);
                                                      ^

ReferenceError: y is not defined

I wasn't expecting this, and don't know how to explain. I have now:

When we redeclare these variables using the same names, we remove access to those names inside the block scope:

...

if (true) {
    // inside this block, we lost access to the old x and y because they're going to be redeclared inside this block scope...but we can't use them yet, they haven't been declared yet
    console.log(`A new block scope - x, y, z: ${x}, ${y}, ${z}`);

    // redeclare variables
    const x = 4;
    let y = 5;
    // now we can use the new x and y, 4 and 5 respectively
    var z = 6;
}
...

Why does this happen, and how exactly does the JavaScript/Node interpreter read the code that causes this error?

halfer
  • 19,824
  • 17
  • 99
  • 186
codyc4321
  • 9,014
  • 22
  • 92
  • 165
  • This SO [answer](https://stackoverflow.com/questions/31219420/are-variables-declared-with-let-or-const-not-hoisted-in-es6) explains this behavior. – Onel Harrison Aug 27 '17 at 03:52
  • tl;dr: You cannot access a variable defined with `let` before it was assigned a value. The `y` in the block shadows the outer `y`, i.e. `y` in `console.log(`A new block scope - x, y, z: ${x}, ${y}, ${z}`);` refers to the inner `y`, which doesn't have a value yet and therefore throws an error. – Felix Kling Aug 27 '17 at 04:11

1 Answers1

1

It's okay to use the old x and y in an new block as long as the new block belongs to the old scope, but since you've created another y in the new block with let, according to ES6, the new y will overwrite the old y with a 'unassigned' value, once it get visited without assigning, an error come out.

if(true) {
    console.log(y);
    {
        const x;
        let y;
        var z;
        // your code
    }
}
Nianyi Wang
  • 712
  • 6
  • 13