Javascript

Are variables declared with let or const hoisted

25 September 2026 · 6 min read

Are variables declared with let or const hoisted

Understanding variable hoisting in JavaScript is crucial for writing clean, predictable code. Many developers are familiar with the behavior of var, but the introduction of let and const in ES6 brought some important changes to how variables are handled. So, are variables declared with let or const hoisted? The short answer is yes, but with a significant twist. This seemingly simple question delves into the core mechanics of JavaScript’s execution context and scoping rules. Let’s explore the nuances of hoisting, scoping, and the temporal dead zone to gain a deeper understanding of how let and const behave.

Hoisting: A Quick Recap

Hoisting is a JavaScript mechanism where declarations of variables and functions are moved to the top of their scope before code execution. With var, this means you can use a variable before its declaration without getting a ReferenceError. However, the value will be undefined.

For example:

console.log(x); // Outputs undefined var x = 10; 

This behavior can lead to unexpected results and make debugging more difficult. let and const were introduced to address these issues, providing more predictable variable handling.

let and const: Hoisted, but Different

Unlike var, variables declared with let and const are hoisted to the top of their scope, but they are not initialized. This creates a period between the start of the scope and the declaration of the variable known as the Temporal Dead Zone (TDZ). Accessing a let or const variable within the TDZ throws a ReferenceError, making your code more robust and preventing unintentional errors.

The Temporal Dead Zone (TDZ)

The TDZ is a crucial concept to grasp when working with let and const. It’s the period within a scope where a variable has been hoisted but not yet declared. Any attempt to access the variable during this period will result in a ReferenceError. This behavior encourages developers to declare variables at the top of their scope, promoting cleaner and more predictable code.

Example:

console.log(y); // Throws ReferenceError let y = 20; 

Scope and Block Scope

let and const introduce block scope, meaning variables declared within a block (e.g., an if statement or loop) are only accessible within that block. This differs from var, which has function scope. Block scoping enhances code organization and reduces the risk of unintended variable overwriting.

Example:

if (true) { let z = 30; console.log(z); // Outputs 30 } console.log(z); // Throws ReferenceError 

Best Practices with let and const

To avoid confusion and potential errors, it’s recommended to always declare variables at the top of their scope. This practice minimizes the TDZ and makes your code easier to read and understand. Additionally, prioritize using const for variables that won’t be reassigned and let for those that will.

  • Declare variables at the top of their scope.
  • Favor const over let when possible.

Following these guidelines will lead to more predictable and maintainable JavaScript code. You’ll find debugging easier and avoid common pitfalls associated with variable hoisting and scoping.

Expert Quote: “The introduction of let and const significantly improved JavaScript’s variable handling, bringing much-needed clarity and predictability to scoping.” - Dr. Axel Rauschmayer, JavaScript expert.

  1. Understand hoisting and the TDZ.
  2. Embrace block scope.
  3. Declare variables at the top of their scope.

For more information, check out this article on MDN about let.

Featured Snippet: While both let and const are hoisted, they are not initialized. Accessing them before declaration results in a ReferenceError due to the Temporal Dead Zone. This contrasts with var, which is hoisted and initialized with undefined.

Learn more about JavaScript. See also: W3Schools JavaScript Let and W3Schools JavaScript Const.

[Infographic Placeholder]

FAQ

Q: What is the key difference between let and var in terms of hoisting?

A: While both are hoisted, var is initialized with undefined, whereas let is not initialized, leading to the TDZ.

By understanding the nuances of let, const, and the TDZ, you can write cleaner, more predictable JavaScript code, reducing the likelihood of unexpected behavior. Adopting best practices like declaring variables at the top of their scope will further enhance code readability and maintainability. This knowledge empowers you to leverage the full potential of modern JavaScript and build robust, reliable applications.

  • Review the key differences between var, let, and const.
  • Practice using let and const in your code to solidify your understanding.

Explore related topics such as closures, scope chains, and execution contexts to deepen your JavaScript expertise. Mastering these concepts will elevate your coding skills and enable you to write more efficient and maintainable code. Start practicing today and unlock the full power of modern JavaScript!

Question & Answer :
I have been playing with ES6 for a while and I noticed that while variables declared with var are hoisted as expected…

console.log(typeof name); // undefined var name = "John"; 

…variables declared with let or const seem to have some problems with hoisting:

console.log(typeof name); // ReferenceError let name = "John"; 

and

console.log(typeof name); // ReferenceError const name = "John"; 

Does this mean that variables declared with let or const are not hoisted? What is really going on here? Is there any difference between let and const in this matter?

@thefourtheye is correct in saying that these variables cannot be accessed before they are declared. However, it’s a bit more complicated than that.

Are variables declared with let or const not hoisted? What is really going on here?

All declarations (var, let, const, function, function*, class) are “hoisted” in JavaScript. This means that if a name is declared in a scope, in that scope the identifier will always reference that particular variable:

x = "global"; // function scope: (function() { x; // not "global" var/let/… x; }()); // block scope (not for `var`s): { x; // not "global" let/const/… x; } 

This is true both for function and block scopes1.

The difference between var/function/function* declarations and let/const/class declara­tions is the initialisation.
The former are initialised with undefined or the (generator) function right when the binding is created at the top of the scope. The lexically declared variables however stay uninitialised. This means that a ReferenceError exception is thrown when you try to access it. It will only get initialised when the let/const/class statement is evaluated, everything before (above) that is called the temporal dead zone.

x = y = "global"; (function() { x; // undefined y; // Reference error: y is not defined var x = "local"; let y = "local"; }()); 

Notice that a let y; statement initialises the variable with undefined like let y = undefined; would have.

The temporal dead zone is not a syntactic location, but rather the time between the variable (scope) creation and the initialisation. It’s not an error to reference the variable in code above the declaration as long as that code is not executed (e.g. a function body or simply dead code), and it will throw an exception if you access the variable before the initialisation even if the accessing code is below the declaration (e.g. in a hoisted function declaration that is called too early).

Is there any difference between let and const in this matter?

No, they work the same as far as hoisting is regarded. The only difference between them is that a constant must be and can only be assigned in the initialiser part of the declaration (const one = 1;, both const one; and later reassignments like one = 2 are invalid).

1: var declarations are still working only on the function level, of course