Closures
A clear, in-depth guide to closures in JavaScript — with worked examples, common pitfalls, and a practice quiz.
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
💡 Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:
- Download Node.js to run JavaScript on your computer
- Use your browser's Developer Console (Press F12) to test code snippets
- Create a .html file with <script> tags and open it in your browser
🎒 Real-World Analogy: A closure is like a backpack that remembers :
- • When a function is created, it packs a "backpack" with all the variables around it
- • Even when the function travels far away (like being passed to another function), it carries its backpack
- • The function can always reach into its backpack and use those remembered variables
- • This is how functions "remember" data even after their parent function has finished!
INTRODUCTION — Why Closures Matter More Than Anything Else in JavaScript
Closures are the heart and soul of JavaScript.
Closure Use Case
What It Does
Real Example
Private variables
Hide data from outside access
Counter that can't be reset
Function factories
Create customized functions
makeMultiplier(5)
Event handlers
Remember context when clicked
Button click with ID
React hooks
useState, useEffect internals
Component state
- Private variables
- Function factories
- Event handlers
- State management
- Asynchronous behavior
- Module patterns
- Encapsulation
- Secure data control
Every professional JavaScript developer — especially those working in React, Node.js, or complex web apps — uses closures every single day, often without noticing.
By the end of this lesson, closures will feel completely natural.
SECTION 1 — Understanding SCOPE (Global, Function, Block, Lexical)
Before closures make sense, you MUST understand scope.
📌 Variables are resolved based on WHERE the code was written, not where it is executed.
1. Global Scope
Anything declared outside a function is global.
Accessible everywhere. Dangerous for large apps.
2. Function Scope
Function boundaries matter a lot in closures.
3. Block Scope (let / const)
Block scoping is essential for fixing closure bugs (you'll see later).
4. Lexical Scope (Most Important)
Inner functions access variables declared where they were written.
SECTION 2 — What Is a Closure? (Simple Definition)
A function that "remembers" variables from its outer scope — even after the outer function has returned.
This is the single most important concept in JavaScript.
The Classic Example:
Even though outer() has finished executing, the inner function keeps access to:
- inner scopes
SECTION 3 — The Real Superpower: Private Variables
JavaScript has no private keyword (until ES2020 classes). Before that, closures were the ONLY way to hide data.
Example: Private Counter
This is true encapsulation — impossible with global variables.
SECTION 4 — Function Factories (Closures Generating Functions)
Closures let you preload data into functions.
Make a Function That Remembers a Number (Multiplier):
- dynamic validators
- React hook generators
- custom loggers
- configuration wrappers
- dependency injection
SECTION 5 — Closures and Event Handlers
Event handlers, timeouts, and interactive websites heavily rely on closures.
Example:
Even after setupButton finishes, the inner arrow function still knows:
- surrounding variables
- the DOM element
That's why closures are essential for UI programming.
SECTION 6 — Closures + Async Code (Critical for Modern JS)
Closures keep variables alive during async operations.
Even though loadUser has returned long before the API finishes, the .then() callback remembers prefix .
- Node.js callbacks
SECTION 7 — Memoization with Closures (Speed Boost Technique)
Memoization = caching results so future calls are instant.
SECTION 8 — SUMMARY & CHEAT SHEET
📋 Quick Reference — Closures
Concept
Pattern
Basic Closure
function outer() { return function inner() {} }
Private Data
let count = 0; return { inc: () => ++count }
Factory
makeAdder(5)(10) // 15
Memoization
Cache results inside closure scope
Event Handler
btn.onclick = () = > log(id)
Lesson 11 Complete — Closures & Scope!
You've mastered one of the hardest concepts in JavaScript. Understanding closures puts you in the top tier of JavaScript developers.
Up next: Prototypes & Classes — understanding how object-oriented programming works in JS! 🧬
Practice quiz
What is a closure in JavaScript?
- A way to close a browser window
- A function with no parameters
- A function that remembers variables from its outer scope even after the outer function has returned
- A loop that runs forever
Answer: A function that remembers variables from its outer scope even after the outer function has returned. The lesson defines a closure as a function that remembers variables from its outer scope, even after the outer function has returned.
What kind of scope does JavaScript use to resolve variables?
- Lexical scope
- Dynamic scope
- Random scope
- Block-only scope
Answer: Lexical scope. JavaScript uses lexical scope: variables are resolved based on WHERE the code was written, not where it is executed.
Given: function outer() { const name = 'Boopie'; function inner() { console.log(name); } return inner; } outer()(); What does this log?
- undefined
- ReferenceError
- null
- 'Boopie'
Answer: 'Boopie'. Through lexical scope, inner() accesses name from where it was written, so calling outer()() logs 'Boopie'.
In the createCounter example, what does counter.count return after two increments?
- 2
- undefined
- 0
- 1
Answer: undefined. count is a private variable trapped in the closure, so counter.count returns undefined; only the returned methods can reach it.
Which statement about a 'var' variable declared inside a function is correct?
- It lives inside the function only (function scope)
- It is global
- It is block scoped to the nearest if
- It cannot be reassigned
Answer: It lives inside the function only (function scope). var variables live inside the function only, which is why console.log(x) outside the function throws an error.
Continue this course
- Previous: Error Handling
- Next: Prototypes & Classes