Does using let and const really prevent hoisting?

Devesh Jadon
Beginner's Guide to Mobile Web Development
3 min readMar 29, 2018

While going through ES6, I came to know about let and const keywords and it was mentioned there that with these keywords we no longer have to worry about hoisting. This made me curious to know how exactly do they do that.

While looking for possible explanations i came across this.

It appears that let declarations (and const, which works the same way) may not be hoisted, since a variable declared using let does not appear to exist before it is assigned a value. however let and const are hoisted (like var, class and function), but there is a period between entering scope and being declared where they cannot be accessed. This period is the temporal dead zone (TDZ).

What’s TDZ now?
ES6 mentions so called TDZ (stands for Temporal Dead Zone) — this is the region of a program, where a variable or a parameter cannot be accessed until it’s initialized (i.e. received a value).

We’ll understand the above statement by going through this example

Here we have two scopes, one is the global scope and the other is the scope of function f.
When control flow encounters this line

console.log(a)

It checks for a’s declaration inside f(), after failing to find it there it checks for it’s declaration in global scope but a is declared after invocation of f().

It will give ReferenceError instead of ReferenceError: a is not defined which is the error that JavaScript throws when it is unable to locate the declaration of currently accessed variable. It answers one thing that our control flow is aware about the declaration of variable we are currently accessing and that’s what hoisting is.

Only problem that our control flow is facing is that even after being aware about declaration of a it is not able get a reference of a. The reason behind this is that variable a has entered a temporal dead zone right at the start of the global scope and only comes out of it when control flow encounters this line

let a = 1;

If it had not been initialized with any value then it would have been assigned undefined because that’s the default value a variable is assigned in JavaScript.

Now, if we take a look at another example

After running this example we’ll not get ReferenceError because a has already been declared and called out of the temporal dead zone before invoking f() and our control flow is able to get the reference of a.

Why only Temporal Dead Zones?

  • To catch programming errors: Being able to access a variable before its declaration is strange. If you do so, it is normally by accident and you should be warned about it.
  • For const: Making const work properly is difficult. Quoting Allen Wirfs-Brock: “TDZs ... provide a rational semantics for const . There was significant technical discussion of that topic and TDZs emerged as the best solution.” let also has a temporal dead zone so that switching between let and const doesn’t change behavior in unexpected ways.

I would recommend reading this technical discussion, It will give you a better insight into the things.

I hope my this effort made you more aware about what happens behind the scenes. From now on if somebody says that let and const are good because they avoid hoisting, just give them a tour of the temporal dead zones.

--

--