JavaScript · Lesson 12 / 32 · English
Scope & Hoisting
Understand the idea. Change the code. Build confidence with one focused experiment.
Read this lesson in தமிழ் ↗.
Start with the idea
Scope determines where a binding can be read. let and const use block scope. Function declarations can be called before their declaration; let and const cannot be read before initialization.
Learning goal: Explain what the example does, predict its result, and change it to solve the practice task.
Step-by-step lesson notes
Scope in JavaScript
Scope determines where a variable is accessible in your code. JavaScript has three levels of scope.
Global, Function, and Block Scope
// Global scope — accessible everywhere
const globalVar = "I'm global";
function myFunction() {
// Function scope — only accessible inside this function
const funcVar = "I'm function-scoped";
console.log(globalVar); // ✅ accessible
console.log(funcVar); // ✅ accessible
if (true) {
// Block scope — only accessible inside this {}
const blockVar = "I'm block-scoped";
let blockLet = "also block-scoped";
var funcScoped = "I'm function-scoped (var!)";
console.log(blockVar); // ✅ accessible
}
// console.log(blockVar); // ❌ ReferenceError
console.log(funcScoped); // ✅ var leaks out of block!
}
// console.log(funcVar); // ❌ ReferenceErrorKey rule: Use const and let — they respect block scope. var ignores blocks and leaks into the enclosing function.
Hoisting
Hoisting is JavaScript's behaviour of moving declarations to the top of their scope before code executes. What gets hoisted — and how — depends on var vs let/const vs functions.
// var is hoisted and initialised as undefined
console.log(x); // undefined (not ReferenceError!)
var x = 5;
console.log(x); // 5
// let/const — hoisted but NOT initialised (Temporal Dead Zone)
// console.log(y); // ❌ ReferenceError: Cannot access 'y' before init
let y = 10;
// Function declarations are fully hoisted
greet(); // ✅ works — function is hoisted
function greet() {
console.log("Hello!");
}
// Function expressions are NOT hoisted
// sayHi(); // ❌ ReferenceError (const) or TypeError (var)
const sayHi = () => console.log("Hi!");Temporal Dead Zone (TDZ)
// TDZ — the zone between the start of the block and
// the point where let/const is declared
{
// TDZ for 'name' starts here
console.log(typeof name); // ❌ ReferenceError (not "undefined"!)
const name = "Alice"; // TDZ ends here
console.log(name); // ✅ "Alice"
}Scope Chain
const level1 = "outer";
function outer() {
const level2 = "middle";
function inner() {
const level3 = "inner";
// Can access ALL outer scopes
console.log(level1); // ✅ "outer"
console.log(level2); // ✅ "middle"
console.log(level3); // ✅ "inner"
}
inner();
// console.log(level3); // ❌ ReferenceError
}
outer();A complete example
Run this complete index.js program in the JavaScript console editor below. The earlier reference fragments may need a browser page or other surrounding setup.
const topic = "JavaScript";
function report() {
const completed = 2;
console.log(topic + ": " + completed);
}
report();
console.log(typeof missingName);Predict first. Reveal the expected result.
JavaScript: 2 undefined
Make one change. See what happens.
Load the example, change a value, predict the output, and run it again. Use the console output to check your reasoning.
Wait for the editor to load, then load this example and press Run.
Powered by the free OneCompiler editor. Code you run is sent to that external service. Keep personal data and secret keys out of your examples.
Put the idea to work
Practice challenge
Try reading completed outside report. What error should you expect?
Reveal the answer and reasoning
A ReferenceError: completed exists only inside the function.
One mistake to avoid: Hoisting does not mean every declaration can be used early. Reading let or const in its temporal dead zone throws a ReferenceError.
Your learning checkpoint
- Explain the example in your own words.
- Complete the challenge before revealing its answer.
- Describe the common mistake and how to avoid it.