Scope & Closures
Master JavaScript's variable scoping rules and the powerful closure pattern that enables data privacy and function factories.
What is Scope?
Scope determines where variables are accessible in your code. It's the "visibility" of variables - which parts of your code can see and use them.
Why Scope Matters
- Prevents variable naming conflicts
- Controls memory usage
- Enables data privacy
- Makes code more predictable
Types of Scope
Global Scope
Variables declared outside any function or block. Accessible everywhere.
const globalVar = "I'm global!";
Function Scope
Variables declared inside a function. Only accessible within that function.
function fn() { var local = "I'm local"; }
Block Scope
Variables declared with let/const inside {}. Only accessible within that block.
if (true) { let block = "I'm block-scoped"; }
// Global scope
const globalVar = "global";
function outer() {
// Function scope
var functionVar = "function-scoped";
if (true) {
// Block scope
let blockVar = "block-scoped";
const alsoBlock = "also block-scoped";
var notBlock = "NOT block-scoped (var)";
}
console.log(notBlock); // Works! var ignores block scope
console.log(blockVar); // ReferenceError!
}
Scope Chain
When JavaScript looks for a variable, it starts in the current scope and moves outward through parent scopes until it finds it (or reaches global scope).
const a = "global";
function outer() {
const b = "outer";
function inner() {
const c = "inner";
console.log(a, b, c); // All accessible!
// Looks: inner scope �?outer scope �?global scope
}
inner();
}
outer(); // Output: "global outer inner"
Closures
A closure is a function that "remembers" variables from its outer scope, even after the outer function has finished executing.
Definition
A closure = Function + Its Lexical Environment
function createCounter() {
let count = 0; // Private variable
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// count is "closed over" - private but persistent!
Practical Uses of Closures
Data Privacy
Create private variables that can't be accessed directly
Function Factories
Generate specialized functions with pre-configured behavior
Memoization
Cache expensive function results for reuse
Event Handlers
Maintain state between events without global variables
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15