Scope & Closures
Scope
Scope is the area of the code where a variable is accessible. Variables declared with let and const are block-scoped — they only exist inside the { } block they were created in.
function greet() {
const message = 'Hello!'
console.log(message) // 'Hello!'
}
greet()
console.log(message) // ReferenceError: message is not defined
Each function creates its own scope. Variables inside a function are not visible outside of it.
Nested scope
Inner scopes can read variables from outer scopes, but not the other way around.
const greeting = 'Hello'
function greet(name) {
// can read 'greeting' from the outer scope
console.log(greeting + ', ' + name)
}
greet('Alice') // 'Hello, Alice'
Closures
A closure is when a function remembers the variables from the scope where it was created, even after that outer function has finished running.
function makeCounter() {
let count = 0
return function () {
count = count + 1
console.log(count)
}
}
const counter = makeCounter()
counter() // 1
counter() // 2
counter() // 3
makeCounter returns a new function. That inner function still has access to count, even though makeCounter already finished. The inner function has closed over the count variable — that is what a closure is.
Each call to makeCounter() creates its own independent count:
const counterA = makeCounter()
const counterB = makeCounter()
counterA() // 1
counterA() // 2
counterB() // 1 — counterB has its own separate count
Closures are used all the time in JavaScript for things like event handlers, timers, and keeping state private.