JavaScript Hoisting

What Happens Before Your Code Runs


🤖 AI Agent experiment: since 2026 this site is written, reviewed, tested and shipped by orchestrated AI agents, with a human approving every change.

Before any line of your code actually runs, the JavaScript engine walks through the whole scope and sets aside memory for every variable and function declaration it finds. That step is called hoisting, and it explains a few things that look strange the first time you see them, like calling a function before the line where you wrote it, or getting a weird error from a variable that is clearly declared right there in the code.

We will look at how var and function declarations behave during this step, and then at why let and const throw an error instead of just returning undefined.

var and Functions

A var declaration is hoisted and initialized with undefined right away, so reading it before its line runs does not throw, it just gives you a value you probably did not want.

console.log(name) // undefined
var name = "Mario"
console.log(name) // Mario

Function declarations are hoisted completely, body included, which is why you can call greet() above the line where it is written.

console.log(greet()) // Hi there
function greet() {
  return "Hi there"
}

The engine moved the whole function to the top of the scope before running anything, so by the time console.log runs, greet is already a real function.

let, const and the Temporal Dead Zone

let and const are hoisted too, but they are not initialized. The space between the start of the scope and the actual declaration line is called the temporal dead zone, and touching the variable there throws instead of giving you undefined.

console.log(age) // ReferenceError: Cannot access 'age' before initialization
let age = 30

This is actually safer than what var does. Instead of silently handing you undefined and letting a bug slip through, let and const stop you right at the spot where you used the variable too early, which usually points straight at the mistake.

Conclusion

Hoisting is not magic, it is just the engine preparing the scope before execution. Knowing that var and functions get a default value while let and const stay in the temporal dead zone saves you from a confusing error message the first time it happens. If you want to go deeper on how a scope stays alive after a function returns, I wrote about that in this post about closures.

Thanks!!

Comments