8. Scope and Hoisting
What Is Scope?
Scope defines **where** a variable or function can be accessed in your code. It’s like the visibility range — some variables are global, others only exist inside functions or blocks.
Global Scope
A variable declared **outside any function or block** is in the global scope. It can be accessed anywhere in your code.
let siteName = "VeryCodedly";
function showName() {
console.log(siteName); // Accessible here
}
showName();
console.log(siteName); // Accessible here tooFunction Scope
Variables declared **inside a function** are only accessible inside that function. They’re private to that function’s code block.
function greet() {
let message = "Hello!";
console.log(message);
}
greet();
console.log(message); // ❌ Error: message is not definedHere, `message` only exists inside `greet()`. Trying to access it outside causes an error.
Block Scope
Variables declared with `let` or `const` are block-scoped — meaning they only exist inside `{}` braces (like loops or if statements).
if (true) {
let color = "mint";
console.log(color); // ✅ Works here
}
console.log(color); // ❌ Error: color is not defined`var`, on the other hand, ignores block scope — it’s function-scoped, not block-scoped. That’s one reason developers prefer `let` and `const`.
Lexical Scope
Functions in JavaScript can access variables from where they were **defined**, not where they’re **called**. This is called **lexical scope**.
function outer() {
let name = "Nia";
function inner() {
console.log(name); // ✅ Can access parent’s variable
}
inner();
}
outer();What Is Hoisting?
Hoisting means that JavaScript moves variable and function declarations to the top of their scope **before code runs**. It doesn’t move values — just the declarations.
console.log(name); // undefined
var name = "Ada";Because of hoisting, the declaration of `name` is moved up, but not the assignment. It’s as if JavaScript rewrote it like this:
var name;
console.log(name); // undefined
name = "Ada";Hoisting with let and const
`let` and `const` are also hoisted — but they’re placed in a **temporal dead zone (TDZ)** until their declaration is reached. Accessing them early causes an error.
console.log(food); // ❌ ReferenceError
let food = "Jollof";Function Hoisting
Function declarations are fully hoisted — you can call them before they appear in the code.
sayHi(); // ✅ Works fine
function sayHi() {
console.log("Hey there!");
}However, **function expressions** and **arrow functions** are not hoisted the same way, so calling them before they’re defined will cause an error.
sayBye(); // ❌ Error
const sayBye = () => {
console.log("Goodbye!");
};Mini Challenge
1. Try declaring a variable with `var`, `let`, and `const` inside an `if` block. 2. See which ones are accessible outside the block. 3. Then test what happens when you call a function before its declaration.
Key Takeaway
Scope defines where variables live. Hoisting defines when they come to life. Mastering both helps you avoid mysterious 'undefined' and 'not defined' errors.