Understanding JavaScript Hoisting: Why console.log(test) Returns Undefined

JavaScript executes code by first compiling function and var declarations within a scope, then running statements top‑to‑bottom, which explains why accessing a var‑declared variable before its assignment yields undefined while referencing an undeclared variable throws an error, as illustrated through detailed examples.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Understanding JavaScript Hoisting: Why console.log(test) Returns Undefined

JavaScript may appear to run code line by line from top to bottom, but in reality it first compiles declarations within the current scope and then executes statements sequentially.

During the compilation phase, function and var declarations are hoisted. The variable name is created, but its assignment is not performed until the execution phase reaches the assignment statement.

Example 1 demonstrates this behavior:

console.log(test); // undefined because only the declaration is hoisted
var test = "你好";   // assignment happens here
console.log(test); // "你好"
console.log(test2); // ReferenceError: test2 is not defined

When the first console.log(test) runs, the variable test has been declared (so no error) but not yet assigned, resulting in undefined. The identifier test2 was never declared, so accessing it throws a ReferenceError.

The compilation steps can be visualized as:

// Hoist var declaration
var test;

// Execution phase
console.log(test); // undefined
test = "你好";
console.log(test); // "你好"
console.log(test2); // ReferenceError

Function declarations follow a similar but slightly different rule: the entire function body is hoisted and assigned to the function name.

test(); // prints "你好"
function test() {
  console.log("你好");
}

Internally this is equivalent to:

// Hoist function as a variable holding the function object
var test = function () {
  console.log("你好");
};

// Execution phase
test();

A more complex example shows how inner function declarations create local bindings that shadow outer variables:

var a = 1;
function test() {
  a = 2; // refers to the outer variable unless a local one is created
  function a() {} // creates a local function named a, hoisted before the assignment
}

test();
console.log(a); // still 1 because the inner <code>a</code> is a separate local binding

During compilation, the inner function a is hoisted, turning a into a local variable inside test. Consequently, the assignment a = 2 modifies the local a, leaving the outer a unchanged.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptexecutionfunctionscopehoistingVar
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

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.