🎯 Learning Objectives
By the end of this lesson, you will be able to:
- Understand global vs local scope
- Explain lexical scope and scope chain
- Understand hoisting behavior with
var,let, andconst - Identify scope-related bugs and avoid them
- Write code that follows best practices for scope
📚 What is Scope?
Scope determines where variables can be accessed in your code. Think of it like the "visibility" of variables - some variables can be seen everywhere, others only in specific places.
Types of Scope
- Global Scope - Variables accessible everywhere
- Local Scope - Variables accessible only in specific areas
- Block Scope - Variables accessible only within
{}blocks
🌍 Global vs Local Scope
Global Scope
Variables declared outside any function or block are in global scope:
let globalVariable = "I'm global!";
function myFunction() {
console.log(globalVariable); // Can access global variable
}
console.log(globalVariable); // Can access global variable
Local Scope
Variables declared inside a function are in local scope:
function myFunction() {
let localVariable = "I'm local!";
console.log(localVariable); // Can access local variable
}
// console.log(localVariable); // Error! Cannot access local variable
🔗 Lexical Scope
Lexical scope means that inner functions can access variables from outer functions:
function outerFunction() {
let outerVariable = "I'm in outer function";
function innerFunction() {
console.log(outerVariable); // Can access outer variable
let innerVariable = "I'm in inner function";
}
// console.log(innerVariable); // Error! Cannot access inner variable
}
⬆️ Hoisting
Hoisting is JavaScript's behavior of moving declarations to the top of their scope before execution.
Hoisting with var
console.log(x); // undefined (not an error!)
var x = 5;
console.log(x); // 5
This is equivalent to:
var x; // Declaration is hoisted
console.log(x); // undefined
x = 5; // Assignment happens here
console.log(x); // 5
Hoisting with let and const
// console.log(y); // Error! Cannot access before declaration
let y = 10;
console.log(y); // 10
// console.log(z); // Error! Cannot access before declaration
const z = 15;
console.log(z); // 15
Function Hoisting
sayHello(); // "Hello!" (works!)
function sayHello() {
console.log("Hello!");
}
But function expressions are not hoisted:
// sayGoodbye(); // Error! Cannot access before declaration
const sayGoodbye = function() {
console.log("Goodbye!");
};
🎯 Practice Exercises
Exercise 1: Scope Understanding
Predict what will be logged and explain why:
Solution:
let globalVar = "global";
function testScope() {
let localVar = "local";
console.log("Inside function - global:", globalVar);
console.log("Inside function - local:", localVar);
}
testScope();
console.log("Outside function - global:", globalVar);
// console.log("Outside function - local:", localVar); // Error!
Exercise 2: Hoisting Behavior
Predict the output and explain the hoisting:
Solution:
console.log("1. var before:", typeof hoistedVar); // undefined
console.log("2. let before:", typeof hoistedLet); // ReferenceError
var hoistedVar = "I'm hoisted!";
let hoistedLet = "I'm not hoisted!";
console.log("3. var after:", hoistedVar); // "I'm hoisted!"
console.log("4. let after:", hoistedLet); // "I'm not hoisted!"
Exercise 3: Scope Chain
Create nested functions and demonstrate scope chain:
Solution:
let globalVar = "global";
function outerFunction() {
let outerVar = "outer";
function innerFunction() {
let innerVar = "inner";
console.log("Inner can see:", globalVar, outerVar, innerVar);
function deepestFunction() {
console.log("Deepest can see:", globalVar, outerVar, innerVar);
}
deepestFunction();
}
innerFunction();
console.log("Outer can see:", globalVar, outerVar);
}
outerFunction();
🚨 Common Scope Mistakes
1. Accidental Global Variables
function badFunction() {
// Missing let/const - creates global variable!
badVariable = "I'm global!";
}
badFunction();
console.log(badVariable); // Works, but bad practice!
2. Variable Shadowing
let name = "Alice";
function greet() {
let name = "Bob"; // Shadows the outer name
console.log("Hello, " + name); // "Hello, Bob"
}
greet();
console.log(name); // "Alice"
3. Loop Variable Issues
// Problem with var in loops
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // Logs 3, 3, 3
}
// Solution with let
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100); // Logs 0, 1, 2
}
🎯 Key Takeaways
- Scope determines where variables can be accessed
- Global scope - accessible everywhere
- Local scope - accessible only within function/block
- Lexical scope - inner functions can access outer variables
- Hoisting - declarations move to top of scope
varis hoisted but initialized asundefinedlet/constare hoisted but not initialized (temporal dead zone)- Always use
let/constinstead ofvar
🚀 Next Steps
Great! You now understand scope and hoisting. In the next lesson, we'll learn about:
- Destructuring - extracting values from arrays and objects
- Spread operator - expanding arrays and objects
- Rest operator - collecting remaining elements
📚 Additional Resources
🎉 Congratulations!
You've mastered JavaScript scope and hoisting! You now understand:
- How variables are accessed in different scopes
- Why hoisting happens and how it affects your code
- How to avoid common scope-related bugs
- Best practices for variable declaration
Practice with the exercises, and get ready for Lesson 2 where we'll learn about destructuring and spread/rest operators!
Next Lesson: Lesson 2: Destructuring & Spread/Rest