- Published on
Closure in javascript
- Authors
- Name
- Ganesh Negi
What is closure in javascript

A closure in javascript is a combination of a function and the scope in which it was created.
This means that even after the outer function has finished executing, the inner function still has access to the variables from its original scope.
Closures enable useful programming techniques such as data encapsulation, currying, and handling asynchronous operations.
Table of content
- Understanding Closure in javascript
- Understanding Scope and Closures in JavaScript
- Understanding Lexical Environment (closure in javascript)
- Why closures are crucial in JavaScript development
- Disadvantages of Closure in javascript
- Key Considerations for closure in javascript
- JavaScript Interview Coding Questions On Closure
- Summary
Closure function in javascript & example of closure in javascript
Example 1: Understanding Closures
var number1 = 2;
var add = function () {
var number2 = 3;
return function () {
return number1 + number2;
};
};
var addNum = add();
console.dir(addNum);
In this example, addNum is a function that retains access to both number1 and number2, even though add() has already completed execution. This behavior occurs due to JavaScript's scope mechanism:
Global Scope:
The variable number1 is declared outside of any function, making it globally accessible. Any function can reference number1 because it exists at the top level.
Closure Scope:
The variable number2 is defined inside the add() function. When add() returns the inner function, that inner function retains a reference to number2 because of closures.
Even though add() has finished running, the returned function still "remembers" number2 due to this preserved scope.
As a result, calling addNum() successfully retrieves and adds number1 from the global scope and number2 from the closure scope.
The console.dir(addNum); statement outputs a detailed breakdown of the function’s properties, including its closure, making it easier to inspect how JavaScript maintains references to variables.
Example 2: When No Closure is Created
var number1 = 2;
var add = function () {
return function () {
return number1 + 5;
};
};
var addNum = add();
console.dir(addNum);
In this example, the inner function does not reference any variables from its immediate outer function (add()). Instead, it relies solely on number1, which is defined in the global scope.
Since there are no variables to capture from add(), a closure is not formed in this case. The inner function simply accesses number1 from the global scope, without needing to preserve any references to its enclosing function’s execution context.
This highlights a key detail about closures: they only occur when an inner function retains access to variables from its enclosing function’s scope. If no such variables are used, the function behaves normally without creating a closure.
Example 3: let vs var in Closures
JavaScript’s let and var have different scoping rules, which can affect how closures work. Consider the following example:
let number1 = 2;
let number2 = 3;
var add = function () {
return function () {
return number1 + number2;
};
};
var addNum = add();
console.dir(addNum);
Key Differences Between let and var in This Context
- Function Scope vs Block Scope:
var is function-scoped, meaning a variable declared with var inside a function is accessible anywhere within that function. let is block-scoped, meaning it is only accessible within the block in which it was declared.
- Script Scope vs Global Scope:
When a variable is declared with let at the top level of a script (outside any function), JavaScript assigns it to the Script scope instead of the Global scope.
This means that in a browser environment, a var-declared global variable becomes a property of window, while a let-declared variable does not. In Node.js, var-declared global variables are attached to the global object, while let and const remain in the module scope instead.
- Why This Matters
Using let and const instead of var helps avoid unintended interactions with the global object, making the code more predictable and reducing potential bugs caused by variable reassignments or unintended global pollution.
Example 4: Closures and Asynchronous Functions
var a = 50;
function async() {
a = 30; // Modifies the global variable
var fn = function () {
console.log(a);
};
setTimeout(fn, 300); // Delays execution of fn by 300ms
console.dir(fn);
}
async();
a = 100; // Output after 300 ms: 100
Explanation
The variable a is initially declared globally with a value of 50.
When async() is executed, a is updated to 30, modifying the global variable.
Inside async(), the function fn is created, which logs the value of a.
fn is passed to setTimeout(fn, 300), meaning it will run after 300 milliseconds.
After async() completes, a is reassigned to 100.
When fn executes after 300ms, it logs 100 instead of 30.
Key Takeaway
Closures maintain a reference to variables, not a snapshot of their values at the time of function creation. Since fn refers to the global variable a, and a was updated to 100 before fn executed, the final output is 100.
This behavior is essential to understand when working with asynchronous JavaScript, as it can lead to unexpected results if variable updates are not carefully managed.
Example 5: Practical Use Case — Private Variables
Closures can be used to create private variables, ensuring that certain values are only accessible through specific functions.
function accountBalance(initialBalance) {
var balance = initialBalance;
return function () {
return balance;
};
}
var getBalance = accountBalance(100);
console.dir(getBalance);
Explanation
The variable balance is declared inside the accountBalance() function and is not directly accessible from outside.
accountBalance() returns an inner function that allows us to retrieve the balance value.
When accountBalance(100) is called, it returns a function that still "remembers" the balance variable due to closures.
Calling getBalance() will return the stored balance, but balance itself cannot be modified or accessed directly.
Why This Is Useful
This pattern helps encapsulate data, preventing unwanted modifications from outside the function. Since balance exists only within accountBalance(), it cannot be altered externally, ensuring controlled access to the value.
Closures provide a powerful way to implement data privacy in JavaScript, making them useful for scenarios like managing user sessions, protecting sensitive data, and creating modular, maintainable code.
Example 6: Closures Hold References, Not Direct Values
This example demonstrates how closures store references to variables rather than capturing their initial values.
(function () {
var number1 = 10;
var number2 = 20;
var add = function () {
return number1 + number2;
};
console.log(add()); // Output: 30 (10 + 20)
number1 = 50;
number2 = 100;
console.log(add()); // Output: 150 (50 + 100)
})();
Explanation
The immediately invoked function expression (IIFE) ensures that number1 and number2 exist in a private scope.
The add function is defined within this scope and retains access to number1 and number2 through closure.
Initially, number1 is 10 and number2 is 20, so add() returns 30.
After updating number1 = 50 and number2 = 100, calling add() again returns 150.
Key Takeaway
Closures don’t store the original values of variables; instead, they maintain references to them. This means that if the variables are updated later, the closure will always use the latest values.
This behavior is crucial when dealing with asynchronous functions, loops, or dynamically changing data, as it ensures that functions always work with the most current state.
Understanding Scope and Closures in JavaScript
Scope in JavaScript determines the visibility and accessibility of variables throughout your code. There are two main types of scope:
Global Scope – Variables that are accessible anywhere in the script.
Local Scope – Variables that are confined to a specific function or block.
Global Scope Example
A variable declared outside any function belongs to the global scope, making it accessible throughout the program.
let globalVar = "I am a global variable";
function showGlobalVar() {
console.log(globalVar); // Accessible inside the function
}
console.log(globalVar); // Accessible anywhere in the script
showGlobalVar(); // Output: I am a global variable
Local Scope Example
A variable declared inside a function is local and cannot be accessed outside that function.
function demoFunction() {
let localVar = "I exist only within this function";
console.log(localVar); // Accessible inside the function
}
demoFunction();
// console.log(localVar); // This will cause a ReferenceError (localVar is not accessible outside)
Understanding Scope Chain
The scope chain defines the order in which JavaScript searches for variables when they are called. If a variable is not found in the immediate function, JavaScript moves outward, checking parent functions until it reaches the global scope.
Example of Scope Chain
let globalVar = "I'm a global variable";
function outerFunction() {
let outerVar = "I'm from the outer function";
function innerFunction() {
console.log(globalVar); // Found in global scope
console.log(outerVar); // Found in outerFunction's scope
}
innerFunction();
}
outerFunction();
How it works:
innerFunction() looks for globalVar inside itself → not found → checks outerFunction() → not found → checks the global scope → found.
innerFunction() looks for outerVar inside itself → not found → checks outerFunction() → found.
Key Takeaways
Global variables are accessible everywhere but should be used carefully to avoid conflicts.
Local variables exist only within their defined function or block.
The scope chain ensures that variables can be accessed from outer scopes if they aren’t found in the immediate function.
Using proper scope management enhances code efficiency, prevents variable conflicts, and improves maintainability.
Understanding Lexical Environment (closure in javascript)In JavaScript, a lexical environment defines the scope in which variables and functions are accessible. It is created when a function is invoked and consists of all the variables and function declarations that exist within that scope.
The lexical environment is determined by where a function is declared, not where it is executed. This means functions retain access to their outer scope even when executed outside their original context—forming closures.
How the Lexical Environment Works
Each function in JavaScript has its own lexical environment, which consists of:
Environment Record
Stores all variables, function declarations, and parameters in the current scope.
Reference to the Outer Lexical Environment
Points to the lexical environment of the function’s parent scope.
Enables access to variables from outer functions.
Example: Lexical Environment in Action
function outerFunction() {
let outerVar = "I belong to the outer function";
function innerFunction() {
console.log(outerVar); // Accessing outerVar through lexical scope
}
innerFunction(); // Calling innerFunction
}
outerFunction();
Breakdown of Execution
When outerFunction runs:
A new lexical environment is created.
outerVar is stored in the environment record of outerFunction.
When innerFunction runs:
JavaScript first looks for outerVar inside innerFunction’s lexical environment.
Since outerVar is not found, it checks the outer lexical environment (from outerFunction).
outerVar is found and logged to the console.
This lookup mechanism is known as the scope chain.
Lexical Environment Structure Representation
In JavaScript, the lexical environment can be visualized as:
LexicalEnvironment = {
EnvironmentRecord: {
// Stores local variables and function declarations
},
OuterLexicalEnvironment: Reference to the parent scope's lexical environment
}
For the previous example, this can be represented as:
outerFunction Lexical Environment:
{
EnvironmentRecord: { outerVar: "I belong to the outer function" },
OuterLexicalEnvironment: Global Scope
}
innerFunction Lexical Environment:
{
EnvironmentRecord: {},
OuterLexicalEnvironment: outerFunction Lexical Environment
}
Closures and the Lexical Environment
A closure is a function that "remembers" the variables from its outer lexical environment, even when executed outside of that environment.
Example of Closure
function createCounter() {
let count = 0; // Stored in the closure
return function () {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // Output: 1
counter(); // Output: 2
Here, the returned function remembers the count variable from createCounter() even after it has finished executing. This is possible because of the lexical environment and its reference to the outer scope.
Key Takeaways
✔ Lexical environment determines variable accessibility based on function declaration, not execution.
✔ Each function has its own environment record that stores variables and function declarations.
✔ Functions retain access to their parent scope through the outer lexical environment reference.
✔ Closures are a result of lexical scoping, allowing functions to maintain access to their outer variables even after execution.

Why closure in javascript are Essential
Closure in javascript are a fundamental concept that significantly enhance code organization, efficiency, and flexibility.
They allow functions to retain access to variables from their parent scope even after the outer function has finished executing.
Why closures are crucial in JavaScript development:
1. Encapsulation and Data Privacy
Closure in javascript enable data encapsulation, meaning variables inside a function cannot be directly accessed from outside. This improves security and prevents accidental modifications.
Example: Private Variables with Closures
function createCounter() {
let count = 0; // Private variable
return {
increment: function () {
count++;
console.log(`Count: ${count}`);
},
getCount: function () {
return count;
}
};
}
const counter = createCounter();
counter.increment(); // Count: 1
console.log(counter.getCount()); // 1
// console.log(count); // Error: count is not accessible directly
Here, count is encapsulated and cannot be accessed directly from outside.
2. Data Persistence
Closure in javascript allow functions to preserve state across multiple executions, even after the outer function has returned.
Example: Remembering Data
function rememberName(name) {
return function () {
console.log(`Hello, ${name}!`);
};
}
const greet = rememberName("Alice");
greet(); // Output: Hello, Alice!
Even though rememberName has finished execution, the returned function still has access to name.
3. Modularity and Reusability
Closure in javascript enable modular programming, allowing the creation of reusable, self-contained functions that manage their own state.
Example: Configurable Functions
function multiplier(factor) {
return function (number) {
return number * factor;
};
}
const double = multiplier(2);
console.log(double(5)); // Output: 10
const triple = multiplier(3);
console.log(triple(5)); // Output: 15
This makes the function reusable for different scenarios.
4. Functional Programming
Closure in javascript are a cornerstone of functional programming, supporting techniques like higher-order functions, currying, and function composition.
Example: Function Currying
function greet(greeting) {
return function (name) {
console.log(`${greeting}, ${name}!`);
};
}
const sayHello = greet("Hello");
sayHello("John"); // Output: Hello, John!
sayHello("Emma"); // Output: Hello, Emma!
Closures allow functions to be broken down into smaller, composable parts.
5. Managing Asynchronous Operations
Closure in javascript are widely used in asynchronous programming (callbacks, promises, setTimeout) to maintain state.
Example: Using Closures in a Timeout
function delayedMessage(message, delay) {
setTimeout(function () {
console.log(message);
}, delay);
}
delayedMessage("This message appears after 2 seconds", 2000);
The inner function retains access to message, even after delayedMessage has executed.
6. Event Handling and DOM Manipulation
Closure in javascript are essential in event handling, allowing event listeners to retain access to variables from their enclosing scope.
Example: Button Click Counter
function buttonClickCounter() {
let count = 0;
document.getElementById("btn").addEventListener("click", function () {
count++;
console.log(`Button clicked ${count} times`);
});
}
buttonClickCounter();
Here, count is preserved across multiple clicks.
7. Memory Management and Performance Optimization
Closure in javascript help manage memory effectively by allowing variables to persist only when necessary, reducing memory leaks.
Example: Preventing Unnecessary Memory Usage
function manageResources() {
let resource = "Heavy Data"; // Simulating a resource
return function () {
console.log(resource); // Access retained only when needed
};
}
const useResource = manageResources();
useResource(); // Output: Heavy Data
By ensuring variables exist only when needed, closures help optimize memory usage.
In Short points:-
Closure in javascript are more than just a JavaScript concept—they are a powerful tool that enables:
✅ Encapsulation for better data privacy.
✅ Persistent state for managing variables across function calls.
✅ Modular and reusable code, improving maintainability.
✅ Functional programming patterns like currying and composition.
✅ Efficient event handling and asynchronous operations.
✅ Memory optimization, reducing performance issues.

Disadvantages of Closure in javascript
Increased Memory Usage:
closure in javascript can retain references to variables and objects even after their parent function has finished executing, leading to higher memory consumption, especially when dealing with large data structures.
Performance Overhead:
Excessive use of closures, particularly within frequently executed functions or deeply nested structures, can slow down execution by adding unnecessary complexity to function calls and memory management.
Risk of Memory Leaks:
If closure in javascript hold references to variables that are no longer needed, they may prevent the garbage collector from reclaiming memory, leading to potential memory leaks and inefficient resource utilization.
Difficult Debugging:
When closure capture mutable variables or are deeply nested, tracking variable changes and execution flow becomes challenging, making debugging more complex and time-consuming.
Scope Retention Issues:
Closure in javascript can unintentionally extend the lifespan of variables beyond their required scope, leading to scope chain pollution, unexpected behavior, and potential conflicts in the execution environment.
Key Considerations for closure in javascript
Lexical Scoping: JavaScript closures adhere to lexical scoping, meaning a variable’s accessibility is determined by its position in the source code rather than the execution context.
Impact on Garbage Collection: Since closures retain references to their outer scope, they can delay garbage collection, keeping variables in memory longer than necessary until the closure itself is dereferenced.
Variable Binding Behavior: Closures capture variables from their outer scope at the moment of their creation, not during execution, which can lead to unexpected results if not managed properly.
Context Preservation: Along with variables, closures also retain the context (this) in which they were defined, affecting how they interact with objects and functions in different execution environments.
Dynamic and Adaptive Nature: Closures are highly flexible, allowing modifications to their captured variables at runtime, making them a powerful tool for creating dynamic and stateful functions
JavaScript Interview Questions and answers on Closure in javascript
- Question 1: What will be the following code output to the console ?
var y = 10; const foo = () => { y = 200; return () => { console.log(y); } } foo()();
Answer
In JavaScript, when a function returns another function, the inner function remembers where it was created. This is called a closure, which means it can still use variables from its parent function, even if it runs somewhere else.
If there are two variables with the same name—one outside the function and one inside—the inner one is used. This is called variable shadowing because the inner variable “hides” the outer one.
So, when the function runs, it picks the inner variable, and the result is 200.
- Question 2: What will the following code output to the console ?
var result = []; for(var i = 0; i < 5; i++) { result[i] = function() { return i; } } console.log(result[0]());
Answer
In JavaScript, when an anonymous function is stored in an array and later executed, it still remembers the outer scope where it was created. This happens because of closures, meaning the function keeps access to variables from its surrounding scope.
In this case, the variable i is declared in the outer scope (probably with var inside a loop). Since var is function-scoped, all the functions inside the array refer to the same i, not a separate copy for each iteration.
By the time we run any of these functions, the loop has already finished, and i has reached its final value—5 (the step when the loop condition failed). That’s why every function in the array will return 5 when executed.
- Question 3: What will be the following code output to the console ?
var result = []; for(var i = 0; i < 5; i++) { result[i] = (function inner(x) { return function() { return x; } })(i); } console.log(result[0]());
Answer
In every iteration of the for loop, an Immediately Invoked Function Expression (IIFE) is executed. This function takes the current value of i as an argument, creating a separate copy for each iteration. Inside the IIFE, this value is stored in a local variable x, ensuring that each function retains its own unique value instead of sharing a single i variable.
Because of this, when any of these stored functions are executed later, they return the specific x value captured during their respective loop iterations.
For example, when calling result[0], it will return 0 because, during the first iteration, i was 0, and that value was assigned to x.
This approach prevents the common issue where functions inside loops end up referencing the final value of i instead of preserving their individual values.
- Question 4: What will be the following code output to the console ?
function abc(a1) { var b1 = a1; return function() { b1 += 10; return b1; } } const fn = run(50); fn(); console.log(fn());
Answer
In the first step, we call the run(50) function, which assigns 50 to the variable b1 and returns a new function. This returned function is then stored in the variable fn.
var fn = run(50); // b1 = 50
Next, when we call fn(), it executes the inner function, which increases the value of b1 by 10. Since b1 is part of the closure, it retains its updated value.
fn(); // b1 = 50 + 10 → 60
When we call fn() again and log the result, b1 increases by another 10, making the final value 70.
console.log(fn()); // b1 = 60 + 10 → 70
Since closures allow the inner function to "remember" and modify b1 across multiple calls, the variable isn’t reset on each function execution. That’s why the final output is 70 instead of resetting to 50 each time.
- Question 5: What will be the following code output to the console ?
for(let i = 0; i < 5; i++) { setTimeout(function() { console.log(i); },1000 + 1); }
Answer
In this case, we use the let keyword inside the for loop, which creates a new instance of i for each iteration. Unlike var, which has function scope, let is block-scoped, meaning each iteration gets its own separate i value.
Since each function inside the loop captures its own unique i, when we execute them later, they will return the values stored during their respective iterations.
For example, if we store these functions in an array and call them one by one, the output will be:
0, 1, 2
This happens because the closure created by the function inside the loop preserves the correct i value for each iteration, avoiding the common issue seen with var, where all functions would reference the final value of i.
- Question 6: What will be the following code output to the console ?
for(var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); },0); }
Answer
What happens in the code?
The for loop runs synchronously, meaning it doesn't wait for setTimeout to complete.
Since var is function-scoped, the variable i is shared across all iterations of the loop.
By the time setTimeout executes after 1 second, the loop has already finished, and i has become 3.
Each function inside setTimeout accesses i from the lexical scope, which now holds the value 3.
Expected vs Actual Output
Expected: 0, 1, 2 at different time intervals.
Actual: 3, 3, 3, because all three functions reference the final value of i.
Summary
what is the closure in javascript
Closure in javascript are a fundamental concept that every developer should master to write efficient and maintainable code. They allow functions to retain access to their original scope, enabling key programming techniques like data encapsulation, private variables, and asynchronous handling.
One of the most important takeaways is that closures store references to variables, not copies of their values. This distinction is crucial when working with loops, callbacks, and asynchronous functions, as it ensures that the latest state of a variable is always used.
By fully understanding closure in javascript, you can write more predictable, bug-free code and develop more advanced JavaScript applications. To deepen your knowledge, consider exploring Node.js, React, and the MERN stack, where closures play a crucial role in optimizing performance and structuring scalable applications. Keep practicing, experiment with different scenarios, and use closures to unlock the full potential of JavaScript in your projects!