Lexical Scope & Hoisting

Where names resolve is fixed by where you wrote them -- and what the engine sets up before running a line.

Syntax// declarations are registered before execution function f() {} // hoisted + callable let x; // hoisted, but TDZ until this line

Lexical scope means a variable is resolved by looking at the nesting of the source code, not by who called the function. The scope chain is decided when you write the code, not when it runs.

Hoisting, precisely

Before executing a scope, the engine registers its declarations:

  • function declarations are fully hoisted -- callable before their line.
  • var is hoisted but initialised to undefined.
  • let and const are hoisted too, but sit in the temporal dead zone until their declaration runs -- touching them early throws.
console.log(a); // undefined (var hoisted)
var a = 1;
console.log(b); // ReferenceError (TDZ)
let b = 2;

The TDZ is a feature: it turns 'used before defined' from a silent undefined into a loud, catchable error.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Call a function declared with function before its definition in the file, relying on hoisting.
  • Avoid using a let variable before its declaration to prevent a ReferenceError from the TDZ.
  • Understand why a var inside an if block pollutes the enclosing function's scope.

More examples

Function declaration hoisted

Function declarations are fully hoisted, so they can be called before they appear in the source.

Example Β· js
console.log(greet("Alice")); // "Hello, Alice" – works before declaration
function greet(name) {
  return "Hello, " + name;
}

var hoisting vs let TDZ

var hoists the declaration and initialises it to undefined; let is in the temporal dead zone until its line.

Example Β· js
console.log(a); // undefined – var is hoisted, not initialised
var a = 10;
// console.log(b); // ReferenceError – TDZ for let
let b = 20;

Function expression is NOT hoisted

A function expression assigned to a var is not callable before the assignment, only the var binding is hoisted.

Example Β· js
// double(2); // TypeError: double is not a function
var double = function (n) { return n * 2; };
console.log(double(3)); // 6

Discussion

  • Be the first to comment on this lesson.
Lexical Scope & Hoisting β€” JavaScript | SoundsCode