I am struggling with this piece of code:
let foo = 'bar';
{
let foo = 'qux';
}
console.log(foo);
The text accompanying this code says:
What does this program log to the console? Why?
Solution: The program logs bar.
Line 1 initializes a variable named foo with the value'bar'. Line 2 starts a block, which creates a new scope for let variables. The variable on line 1 is still visible at this point, but line 3 declares a new variable named foo that shadows (hides) the variable from line 1. This second variable gets initialized to 'qux', but it goes out of scope on line 4 when the block ends. That brings foo from line 1 back into scope, so line 6 logs its value: bar. Source: https://launchschool.com/books/javascript/read/variables#variablesandvariablenames
My expectation was that the global variable foo
would be visible from inside the code block and still equal to 'foo' before it is redeclared. I checked the output of foo
before and after redeclaration to find out if I was right:
let foo = 'bar';
{
console.log(foo); // should be 'bar', but throws an error: VM786:4 Uncaught ReferenceError: Cannot access 'foo' before initialization
let foo = 'qux';
console.log(foo); // should be 'qux'
}
console.log(foo); // should be 'bar'
The code throws an error when run in the console. When I step through it in the debugger, the local foo
is 'undefined' in the first line of the code block, while I expected it to still be "bar' (until it is redeclared).
To find out, I read about the lexical environment in JavaScript:
When the script starts, the Lexical Environment is pre-populated with all declared variables. Initially, they are in the “Uninitialized” state. That’s a special internal state, it means that the engine knows about the variable, but it cannot be referenced until it has been declared with let. It’s almost the same as if the variable didn’t exist. Source: https://javascript.info/closure
My assumption: The above process also happens when a new code block is started (not just when a whole new script is run): The variables declared inside it are added to the lexical environment of the block, but cannot be referenced yet.
Is this a correct description of what is happening here? Is it the reason why foo
is not 'bar' in the first line of the code block?
Thank you so much!