- Abstraction
- AI pair programming
- Algorithm
- API
- Array
- Array methods
- Booleans
- Callback
- Class
- Class members
- Closure
- Code refactoring
- Comment
- Compiler
- Computer programming
- Conditional statements
- Constant
- Constructor
- Coupling and Cohesion
- Data types
- Debugging
- Decorator
- Dependency
- Destructuring
- Dictionary
- Enum
- Event
- Exception / Error handling
- Function
- Generic / Template
- Higher-order function
- IDE
- Immutability
- Inheritance
- Input validation
- Integer
- Interface
- Iteration patterns
- Legacy code
- Loop
- Machine learning
- Memoization
- Memory and references
- Method
- Module
- Null / Undefined / None
- Null safety / Optional values
- Object
- Object-Oriented Programming (OOP)
- Operator
- Parameter
- Parsing
- Promise and Async/Await
- Prompt engineering
- Recursion
- Regular expression
- Return statement
- Rollback
- Runtime
- Scope
- Script
- Sequence
- Set
- Spaghetti code
- Spread and Rest operators
- State management
- String
- Switch statement
- Synchronous vs Asynchronous execution
- Syntax
- Technical debt
- Ternary operator
- Testing
- This / Self
- Tuple
- Type casting
- Type conversion
- Variable
- Vibe coding
- Webhook
PROGRAMMING-CONCEPTS
Closure: Definition, Purpose, and Examples
A closure is a function that retains access to variables from the scope where it was created, even after that scope has finished executing. In other words, the function “remembers” its surroundings.
Closures are used across many languages to preserve state, customize behavior, and build flexible, composable logic. They show up in everyday programming, especially when working with callbacks, event handlers, and functional programming patterns.
What a Closure Really Is
A closure forms when:
- A function is defined inside another function
- The inner function uses variables from the outer function
- The outer function returns the inner function (or passes it elsewhere)
The key idea:
The inner function keeps access to the outer function’s variables, even after the outer function is done executing.
This ability to “carry” context makes closures powerful for creating dynamic and stateful behavior without relying on classes or global variables.
Closures in JavaScript and TypeScript
JavaScript uses closures everywhere — in event handlers, timers, React components, and countless utilities.
Simple closure example
function createCounter() {
let count = 0; // captured variable
return function () {
count++;
return count;
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
Why this works:
count lives inside createCounter(), but the returned function keeps a reference to it. The outer function finishes, but count stays alive through the closure.
Customizing behavior with closures
function multiplier(factor) {
return function (value) {
return value * factor;
};
}
const double = multiplier(2);
const triple = multiplier(3);
double(4); // 8
triple(4); // 12
Each closure stores its own factor, creating reusable functions with different behavior.
Closure in a TypeScript example
function addSuffix(suffix: string) {
return function (word: string): string {
return word + suffix;
};
}
const addLy = addSuffix("ly");
addLy("quick"); // "quickly"
Types help enforce what each closure returns and captures.
Closures in Python
Python closures follow the same pattern using nested functions.
Python
def make_adder(x):
def add(y):
return x + y
return add
add5 = make_adder(5)
add5(10) # 15
x remains accessible because add() carries it along.
Mutating closed-over values
Python requires the nonlocal keyword when modifying a captured variable.
Python
def running_total():
total = 0
def add(amount):
nonlocal total # allows modification
total += amount
return total
return add
counter = running_total()
counter(5) # 5
counter(3) # 8
Closures become a lightweight way to track internal state.
Closures in Swift
Swift closures are similar to anonymous functions or lambdas.
Basic closure capturing a value
func makeIncrementer(amount: Int) -> () -> Int {
var total = 0
let incrementer = {
total += amount
return total
}
return incrementer
}
let incrementByTwo = makeIncrementer(amount: 2)
incrementByTwo() // 2
incrementByTwo() // 4
Swift captures variables by reference, letting closures modify the original values.
When to Use Closures
Closures are helpful wherever you need functions that carry context or create custom behavior.
1. Preserving state without classes
Instead of storing counters or values globally, closures encapsulate state neatly inside a function.
2. Creating function factories
You can build specialized functions by capturing configuration values, like multipliers, formatters, or validators.
3. Callbacks and event handlers
Closures provide access to surrounding variables without needing to pass everything explicitly.
4. Functional programming patterns
Mapping, filtering, reducing, currying, and composition often rely on closures.
5. React components
Even though React hooks rely on closures internally, the pattern is invisible to most beginners — but it’s closures that preserve state across re-renders.
Examples of Closures in Real Code
Example 1: Event handlers (JavaScript)
function setupButton(message) {
const button = document.querySelector("button");
button.addEventListener("click", () => {
console.log(message);
});
}
setupButton("Welcome!");
The arrow function remembers message when the event happens later.
Example 2: Creating reusable formatting functions (Python)
Python
def currency_formatter(prefix):
def format(amount):
return f"{prefix}{amount:.2f}"
return format
usd = currency_formatter("$")
usd(19.99) # "$19.99"
This pattern appears constantly in real applications — a function is created, customized, and reused.
Example 3: Delayed execution (JavaScript)
function later(msg) {
return () => console.log("Later:", msg);
}
const task = later("Save completed");
setTimeout(task, 1000);
task still knows what msg was, even though later() has already executed.
Closures vs Regular Functions
Regular functions run with the variables available at the moment they execute.
Closures run with the variables available at the moment they were created.
This distinction explains why closures feel “stateful”:
- They keep data alive
- They remember old values
- They customize behavior
Closures make functions behave more like objects: they can hold internal state without being classes.
Common Mistakes with Closures
1. Expecting fresh values each time
Because closures remember state, they might preserve a value longer than expected.
2. Capturing variables inside loops
In JavaScript, loops once caused surprising behavior because closures captured references, not values. Modern JS solves most of this with let instead of var.
3. Using closures when a simple function is enough
Closures add power but also complexity — sometimes a plain function is clearer.
4. Accidental memory retention
Keeping references alive longer than necessary can cause memory growth in long-running applications.
Summary
A closure is a function that retains access to the variables from the environment where it was created. This lets the function preserve state, customize behavior, and react to context long after the original scope has finished. JavaScript, TypeScript, Python, and Swift all rely on closures for callbacks, function factories, and flexible programming patterns. Closures keep code modular, expressive, and powerful — especially when building dynamic applications.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.