let, hoisting, and the temporal dead zone with vanilla JS
Yesterday, we looked at how variables declared with let
treat scope a bit differently than variables declared with var
. Today, we’re going to look at how they treat hoisting different.
If you don’t know what hoisting is yet, start with this article on variable hoisting in JavaScript.
Traditional hoisting with var
When a JavaScript file first loads, the browser does any initial pass and stores any variable names it finds to memory. This is called hoisting.
When the browser goes to actually execute the file, it already knows what the variable names are, but does not know what their values are.
In the example below, v
was hoisted. Trying to log its value before it’s declared logs undefined
, but doesn’t throw an error. The browser knows it exists, but it gets a temporary value of undefined
until the declaration happens.
// The variable name is hoisted, but the value is undefined until it's declared
// logs undefined
console.log(v);
// The value gets defined
var v = 'declare with var';
// logs "declare with var"
console.log(v);
Hoisting with let
Variables declared with let
are still hoisted, but they don’t automatically receive a value of undefined
the way variables declared with var
do.
The browser knows they exist, but has no value at all for them. Trying to log a variable declared with let
before it’s actually declared throws an error.
// While the name was hoisted, it has no defined value and throws an error
// Uncaught ReferenceError: l is not defined
console.log(l);
// The value gets defined
let l = 'declare with let';
// logs "declare with var"
console.log(l);
This gap between when a variable declared with let
is hoisted and when it actually gets declared is known as the temporal dead zone.
Steve Griffith has a great video on this if you want to learn more.
This is actually a good thing
In yesterday’s article, I wrote that I like the more strict behavior that let
introduces, and this is another example.
The let
operator forces you to declare a variable before trying to use it, and I think that’s a good thing.