Fundamentals 9 min read

Why Does var Print 2 Twice? Unraveling JavaScript’s Function Scope and Hoisting

This article explains why a JavaScript function using var prints “2” twice, by detailing var’s function scope, variable hoisting, the compilation and execution phases, and contrasting the behavior with let and const, while offering practical coding recommendations to avoid common pitfalls.

FunTester
FunTester
FunTester
Why Does var Print 2 Twice? Unraveling JavaScript’s Function Scope and Hoisting

Misconception: var Is Not Block‑Scoped

In JavaScript, a variable declared with var has function scope, not block scope. Whether inside if, for, or while blocks, var declarations are hoisted to the top of the containing function, creating a single binding that can be overwritten.

This leads many newcomers, especially those from languages like Java or C++, to mistakenly treat var as block‑scoped, misjudging variable lifetimes and overwrite behavior.

Execution Flow Diagram

Breaking down the execution order clarifies what happens. For the example function, the engine processes it as follows:

function test() {
  // Compilation/registration phase: var x is bound at the top (initial value undefined)
  var x; // binding exists but not yet assigned
  x = 1; // execution phase: assign 1
  if (true) {
    // Reassign the same binding
    x = 2;
    console.log(x); // prints 2
  }
  console.log(x); // prints 2 (same binding)
}

test(); // prints 2 and 2

The key steps are: 1) declaration phase registers the variable name; 2) execution phase assigns values; 3) the if block does not create a new var x, it reassigns the existing one; 4) both console.log calls output the current value of the same variable.

What If We Use let or const?

Replacing var with let or const changes the behavior because they are block‑scoped:

function test() {
  let x = 1;
  if (true) {
    let x = 2; // new block‑scoped variable
    console.log(x); // prints 2
  }
  console.log(x); // prints 1
}

test(); // prints 2 and 1

Here the if block creates a separate x, so the outer x remains unchanged. Additionally, let and const do not undergo traditional hoisting; they are hoisted to the top of their block but remain in a Temporal Dead Zone until initialization, preventing accidental undefined outputs.

Extension: The Essence of Variable Hoisting

Hoisting is not magic. Before a function runs, the engine scans for all var declarations, registers their names in the function scope, and initializes them to undefined. Example:

function demo() {
  console.log(a); // undefined, not an error
  var a = 10; // assignment occurs later
}

demo(); // logs undefined then finishes

Using let or const would instead throw a ReferenceError when accessed before initialization, making such bugs explicit.

Coding Recommendations

Based on the understanding of scope and hoisting, follow these practices to reduce maintenance cost and errors:

Avoid var in modern projects; prefer const for immutable references and let for mutable ones.

Limit variable scope to the smallest necessary region; declare and initialize close to where they are used.

Enable static analysis tools (e.g., ESLint) with recommended rules to catch duplicate declarations and unsafe hoisting.

In loops or asynchronous callbacks, use let for block isolation or explicitly capture values with closures.

Establish team guidelines that restrict var usage and enforce them through code review and CI pipelines.

Summary

Key takeaways: var: function‑scoped, hoisted, single binding per function, easy to overwrite. let / const: block‑scoped, Temporal Dead Zone before initialization, safer.

The interview question’s answer is “2 2” because var overwrites the same binding.

Recommended practice: use const / let, keep scopes minimal, enable linting, and enforce coding standards.

JavaScriptconstletscopehoistingVar
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

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.