Understand Declarations Before Execution

Understand Declarations Before Execution

Before running statements, JavaScript establishes declaration bindings. var can be read as undefined before its assignment, while let and const are unavailable until initialization. This distinction is more precise than imagining source lines physically moving.

Before this topic, review Look Up Names Where Code Was Defined if its terms are unfamiliar.

What you’ll learn

  • Explain understand declarations before execution through the school example.
  • Trace the shown operations and distinguish their result from displayed output.
  • Make the practice change and explain its consequence: The early var read remains undefined; the later assignment stores 80.

Work through the school example

This is JavaScript using language features and the host console. Read the initial values, then follow each operation to its displayed result. A declaration names a value, a function call performs an operation, and console.log displays its arguments.

JavaScript · school.js · complete example

console.log(marks);
var marks = 72;
console.log(marks);

Expected output

undefined
72
Run in JavaScript compiler →

Introduction to JavaScript Hoisting

Ever wondered why you can use a variable before it's defined in JavaScript? That's because of a concept called hoisting. At its core, hoisting is JavaScript's way of setting up memory before it starts running your code — quietly and invisibly behind the scenes.

What is Hoisting?

Hoisting is JavaScript’s default behavior of moving declarations to the top of the current scope (either function or global). But it doesn't move initializations.

It’s like the engine says, “Let me prepare all the variable and function names I’ll need before I begin.”

Variable Hoisting with var

Variables declared with var are hoisted — their declarations, not their initializations.

console.log(x);
var x = 5;
undefined

Why undefined and not a ReferenceError?

Behind the scenes, the JavaScript interpreter rewrites it like this:

var x;
console.log(x);
x = 5;

This means the var is hoisted, but its 5 isn't — hence undefined.

Variable Hoisting with let and const

Things get stricter with let and const. Yes, they are hoisted, but they live in the Temporal Dead Zone (TDZ) from the start of the block until the declaration is encountered.

console.log(y);
let y = 10;
ReferenceError: Cannot access 'y' before initialization

Here’s what you need to know:

  • let and const are hoisted.
  • But they are not initialized.
  • Accessing them before declaration throws an error.

Function Hoisting

Function declarations are fully hoisted — both their name and body.

greet();

function greet() {
  console.log("Hello there!");
}
Hello there!

JavaScript reads this as if the function was defined before the call. However, function expressions are a different story.

Function Expressions are NOT Hoisted (Well, Not Like You Think)

sayHi();

var sayHi = function() {
  console.log("Hi!");
}
TypeError: sayHi is not a function

What happened here? sayHi is hoisted as a var — which means it’s set to undefined — not as a function. So calling it throws an error.

Hoisting in Functions and Block Scope

Let's peek into a function to see hoisting at work:

function test() {
  console.log(a);
  var a = 20;
}
test();
undefined

Why? Because var a is hoisted to the top of the function scope, just like this:

function test() {
  var a;
  console.log(a);
  a = 20;
}

Block Scope and Hoisting

What happens inside a block?

{
  console.log(msg);
  let msg = "Block scope hoisting!";
}
ReferenceError: Cannot access 'msg' before initialization

Even though let msg is hoisted to the top of the block, it’s still uninitialized — welcome to the TDZ.

Hoisting Order: A Summary

Type Hoisted? Initialized? Accessible Before Declaration?
varYesYes (to undefined)Yes
letYesNoNo (TDZ error)
constYesNoNo (TDZ error)
Function DeclarationYesYesYes
Function ExpressionOnly variable nameNoNo (TypeError)

Best Practices to Avoid Hoisting Confusion

  • Always declare variables at the top of their scope.
  • Use let and const to prevent silent hoisting bugs.
  • Declare functions before you call them — even though declarations are hoisted, it improves readability.

Conclusion

Hoisting is one of those quirks that give JavaScript its charm — and sometimes, its confusion. But once you understand the rules, especially the differences between var, let, const, and functions, you’ll be well-equipped to write cleaner, more predictable code.

Remember, JavaScript is not reading your code top-down as you wrote it — it’s reordering it in memory before it runs. Once you embrace that mindset, hoisting becomes less magical and more logical.

Recognize the important boundary

Reading let before initialization throws ReferenceError even with typeof. Function declarations and function expressions do not have identical early-call behavior.

Try a small variation

JavaScript · original source for practice

console.log(marks);
var marks = 72;
console.log(marks);

Your task: Replace 72 with 80. Predict the result before running the edited program.

The source is repeated here. If the edit targets the HTML rather than the script, use the markup repeated below; the worked answer also repeats the changed markup.

Worked answer and reasoning

The early var read remains undefined; the later assignment stores 80.

JavaScript · complete worked variation

console.log(marks);
var marks = 80;
console.log(marks);

Expected output

undefined
80
Run in JavaScript compiler →

Predict the original program

JavaScript · original program for this question

console.log(marks);
var marks = 72;
console.log(marks);
What does the original JavaScript program display, in order?
Choose one answer. You can try again.

Answer and explanation

undefined → 72

Before running statements, JavaScript establishes declaration bindings. var can be read as undefined before its assignment, while let and const are unavailable until initialization. This distinction is more precise than imagining source lines physically moving. Reading let before initialization throws ReferenceError even with typeof. Function declarations and function expressions do not have identical early-call behavior.

Keep the useful idea

Before running statements, JavaScript establishes declaration bindings. var can be read as undefined before its assignment, while let and const are unavailable until initialization. This distinction is more precise than imagining source lines physically moving.

Check your variation against this explanation: The early var read remains undefined; the later assignment stores 80.

Use the JavaScript array reference library for individual array operations and boundary tests to check a rule independently.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Keep Access to an Outer Binding →