DEV Community

mmvergara
mmvergara

Posted on

1 1 1 1 1

Javascript Hoisting - What Moves and What Stays

Think of hoisting like setting up a stage before a play. Before the code runs (during the "creation phase"), JavaScript moves all declarations to the top of their scope like stagehands moving props into place before the curtain rises. The only catch is that the declarations are moved, not the initializations.

According to the ECMAScript specification, this behavior is actually part of how JavaScript creates what's called the "lexical environment" during the creation phase. But let's not get too technical just remember that JavaScript does a "pre-scan" of your code before running it.

var Hoisting

console.log(x); // Outputs: undefined
var x = 5;
console.log(x); // Outputs: 5
Enter fullscreen mode Exit fullscreen mode

In this example, the var declaration var x is hoisted to the top of the scope, but the initialization x = 5 is not. This is why the first console.log(x) outputs undefined instead of throwing an error. The variable x exists, but it hasn't been assigned a value yet.

let and const in the Temporal Dead Zone (TDZ)

console.log(y); // Throws a ReferenceError: Cannot access 'y' before initialization
let y = 10;
console.log(y); // Outputs: 10
Enter fullscreen mode Exit fullscreen mode

In this example, the let declaration let y is hoisted, but it is placed in the Temporal Dead Zone (TDZ) until the line where it is initialized. Trying to access y before its initialization results in a ReferenceError. This behavior is different from var, which would simply return undefined in a similar situation.

this also includes anything that is declared using let or const including functions ofcourse

The TDZ (Temporal Dead Zone)

Speaking of the temporal dead zone, this is where let and const declarations live before they're initialized. Unlike var which returns undefined when accessed before initialization, these modern declarations will throw an error. The ECMAScript spec calls this behavior "temporal dead zone semantics", but I just call it "JavaScript keeping us honest".

A slightly harder example

function setupEventHandler() {
  handleClick(); // Works!

  const config = {
    debug: true,
  };

  function handleClick() {
    if (config?.debug) {
      // Undefined!
      console.log("Debug mode");
    }
  }
}

setupEventHandler();
Enter fullscreen mode Exit fullscreen mode

See what happened there? The function declaration handleClick is hoisted, so we can call it early. But that object config? It stays right where it is. This is why accessing config inside handleClick gives us undefined, we're trying to read the script before its ready.

The Class Gotcha

Class hoisting doesn't work quite the same way.

const dog = new Animal(); // Throws an error!

class Animal {
  constructor() {
    this.type = "mammal";
  }
}
Enter fullscreen mode Exit fullscreen mode

While classes are hoisted, they stay in a "temporal dead zone" until their definition is evaluated. This means you can't access them before they're declared.


Just remember declarations are moved to the top, but initializations stay put.

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • --last-failed: Zero in on just the tests that failed in your previous run
  • --only-changed: Test only the spec files you've modified in git
  • --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Practical examples included!

Watch Video 📹️

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay