What is the temporal dead zone?
let
and const
have two broad differences from var
:
- They are block scoped.
- Accessing a
var
before it is declared has the resultundefined
; accessing alet
orconst
before it is declared throwsReferenceError
:
console.log(aVar); // undefined
console.log(aLet); // Causes ReferenceError: Cannot access 'aLet' before initialization
var aVar = 1;
let aLet = 2;
If let is not hoisted or they goes in temporal dead zone, then why this snippet is throwing error, when it could have just used the global reference
The answer to your question is in your title: the variable is in a "temporal dead zone", which is just a name for the behaviour you're seeing.
Take this explanation on MDN:
Unlike variables declared with
var
, which will start with the value undefined,let
variables are not initialized until their definition is evaluated. Accessing the variable before the initialization results in aReferenceError
. The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.
The start of the block is the opening {
and your console.log(a)
comes before let
statement, so it is in this "dead zone".
Why does it work that way? Because it helps programmers detect bugs in their code caused by confusion between variables with the same name in different scopes.
Why does the temporal dead zone exists?
It makes sense for a variable to exist from the moment it is defined. Due to the way variables from an outside scope are accessible within nested scopes, the following code is very confusing:
var foo = 'out';
function bar () {
foo = 'in';
console.log(foo);
var foo;
}
bar();
What does the function bar()
do? It creates a new variable called foo and assigns 'in'
to it before showing it in the console. The variable from the outside scope is still equal to 'out'
after that. So it's a much smarter thing to define variables before you use them. I believe the fact that you can use a variable before it is declared is only a question of implementation simplicity and efficiency, but I'm boldly guessing here.
However, in JS, variables created with the var
keyword are accessible from within their function, not their block. This allows more permissive syntax like the following:
function setGameMode (mode) {
if (mode === 'peaceful') {
var count = 0;
for (var i = 0; i < mobs.length; ++i) {
if (mobs[i] instanceOf EvilMob) {
mobs[i].despawn();
++count;
}
}
console.log('Removed ' + count+ ' evil mobs out of ' + i);
mobSpawner.evil = false;
} else if (mode ==='chaotic') {
var count = 0;
for (var i = 0; i < mobs.length; ++i) {
if (mobs[i] instanceOf NiceMob) {
mobs[i].despawn();
++count;
}
}
console.log('Removed ' + count + ' nice mobs out of ' + i);
mobSpawner.nice = false;
}
}
The i
variable still exists after the for loop thanks to function-scoped variables. This is also why the var
keyword allows you to define a variable twice. It just wouldn't be practical if you were forced to write var
only once. With a let
variable, this "loose" feature becomes useless as these variables should be freed as soon as they are no longer needed.
When you call a function in most programming languages, the execution environment creates a space in memory for the variables you'll need. Here, there's no way to tell if the variable i
will be needed without actually running the code because it's inside an if block. Still, since JS has function-scoped variables, it has to create the variable from the start of the function. There's no need for this in the case of let
variables.
As for the reason behind typeof someundefinedvar
returning 'undefined', well it's because you need a way to check for variables that might have been declared in outside scopes. However, you don't need that feature for variables that are block-scoped. let
variables are meant to be used immediately and thrown away.
ECMAScript 2015 Temporal Dead Zone
That's the way it goes:
Temporal dead zone and errors with let
In ECMAScript 2015,
let
will hoist the variable to the top of the block. However, referencing the variable in the block before the variable declaration results in a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the declaration is processed.
Related Topics
Asynchronous Process Inside a JavaScript For Loop
How to Get Image Size (Height & Width) Using JavaScript
Why Is Setstate in Reactjs Async Instead of Sync
Get the Highlighted/Selected Text
Difference Between Call and Apply
Creating a New Dom Element from an HTML String Using Built-In Dom Methods or Prototype
Difference Between the '=' and '==' Operators and What Is '==='? (Single, Double, and Triple Equals)
How to Get Function Parameter Names/Values Dynamically
Usage of the Backtick Character (') in JavaScript
How to Select Text Nodes With Jquery
How to Use the : (Conditional) Operator in JavaScript
What Does "Use Strict" Do in JavaScript, and What Is the Reasoning Behind It
How to Enumerate the Properties of a JavaScript Object
Updating Address Bar With New Url Without Hash or Reloading the Page
How to Detect If Multiple Keys Are Pressed At Once Using JavaScript
Passing Data to a Bootstrap Modal
Get Selected Text from a Drop-Down List (Select Box) Using Jquery