Frontend Development 7 min read

Understanding JavaScript Hoisting: var, let, const and Function Declarations

This article explains how JavaScript engines hoist function and variable declarations, compares the behavior of var, let, and const during creation, initialization, and assignment, and demonstrates the resulting runtime errors and output through clear code examples.

MaoDou Frontend Team
MaoDou Frontend Team
MaoDou Frontend Team
Understanding JavaScript Hoisting: var, let, const and Function Declarations

Key Points

Function hoisting

Differences in hoisting for var, let, and const

JavaScript performs a preprocessing step before executing code, moving variable and function definitions (creation, initialization, assignment) to the top of their scope. The exact behavior varies slightly between engines.

Code Example 1 (function declaration hoisted):

<code>// foo调用在定义之前
foo();
function foo() {
  console.log('hello world');
}
// hello world</code>

Code Example 2 (var assigned a function, not hoisted):

<code>// 报错
foo();
var foo = function () {
  console.log('hello world');
};
// TypeError: foo is not a function</code>

Code Example 3 (var hoisted, initialization not):

<code>// 不报错
console.log(`a is ${a}`);
var a = 'hello world';
// a is undefined</code>

Code Example 4 (let hoisted, initialization not):

<code>// 报错
console.log(`a is ${a}`);
let a = 'hello world';
// ReferenceError: a is not defined</code>

Code Example 5 (const hoisted, no assignment phase):

<code>// 报错
console.log(`a is ${a}`);
const a = 'hello world';
// ReferenceError: a is not defined</code>

The three stages of creation, initialization, and assignment are treated differently:

Function definitions have all three stages hoisted.

var declarations have creation and initialization hoisted; assignment is not.

let declarations have creation hoisted only; initialization and assignment are not.

const declarations have creation hoisted; initialization is not hoisted and there is no separate assignment phase.

Detailed walkthrough of the examples:

In code1, the function is created, initialized to undefined, then assigned the function body before the call, so the call succeeds.

In code2, var creates foo and initializes it to undefined, then the call occurs before the assignment, causing a TypeError.

Code3 behaves like code2: the variable is initialized to undefined, so the logged value is undefined.

In code4, let creates the binding but does not initialize it; the console.log runs before initialization, throwing a ReferenceError.

Code5 follows the same pattern as code4.

Hoisting also respects a priority order. Consider the following code:

<code>console.log(foo);
function foo() {
  console.log('hello world');
}
var foo = 1;
console.log(foo);
// [Function: foo]
// 1</code>

The engine first creates the var binding (foo = undefined), then processes the function declaration, overwriting the binding with the function object, then executes the first log (showing the function). Later the var assignment runs, changing foo to 1, so the second log outputs 1. Replacing var with let would raise a SyntaxError because let does not allow a second creation.

Another interesting let behavior:

<code>let x = x; // x之前未定义过
// Uncaught ReferenceError: Cannot access 'x' before initialization

x = 1;
// Uncaught ReferenceError: x is not defined</code>

Here, let creates the binding, but the right‑hand side reference occurs before initialization, triggering a ReferenceError and leaving the binding in the temporal dead zone, so subsequent accesses also fail.

ES6 class declarations are also hoisted similarly to let/const; referencing a class before its declaration throws an exception.

Best practice: Declare before you use.

JavaScriptconstletfunctionES6hoistingvar
MaoDou Frontend Team
Written by

MaoDou Frontend Team

Open-source, innovative, collaborative, win‑win – sharing frontend tech and shaping its future.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.