What is closure?
Closure is a fundamental concept in JavaScript, which enables functions to remember and access their lexical scope even when they are executed outside of that scope. It occurs when a function retains access to variables from its outer scope even after the outer scope has finished executing.
Let's understand two vital concepts.
1: What is lexical scope?
2: What does it mean for a parent function to have finished expecting?
Let's understand lexical scope with examples
Lexical scope defines how variable names are resolved in nested functions.
Imagine you have a set of nesting dolls. Each doll is placed inside another. The smaller doll can see and access everything within the doll it's placed in, as well as everything outside.
In programming terms:
Outer Scope: This is like the larger nesting doll. It contains variables and functions.
Inner Scope: This is like the smaller nesting doll inside the larger one. It can access its own variables as well as those in the outer scope.
Examples
Lexical Scope with Global Variable
let globalVariable = 'I am global';
function myFunction() {
console.log(globalVariable); // Accessing globalVariable
}
(); // Output: "I am global"
In this example, globalVariable
is defined in the global scope. Any function defined within this scope has access to globalVariable
directly.
Example 2
Lexical Scope in Nested Functions
function outer() {
let outerVar = 'Outer Variable';
function middle() {
let middleVar = 'Middle Variable';
function inner() {
console.log(outerVar + ' ' + middleVar);
}
inner();
}
middle();
}
outer(); // Output: "Outer Variable Middle Variable"
console.log(middleVar); // Output: ReferenceError: middleVar is not defined
Here, inner
has access to both outerVar
from its outer scope (outer
) and middleVar
from its immediate outer scope (middle
) but cannot be accessed outside the middle function
. This showcases how lexical scope works with nested functions.
So, lexical scope is all about where you place your variables in your code and how that affects where they can be accessed. It's a fundamental concept in understanding how JavaScript (and many other programming languages) handles variable visibility and accessibility.
What does it mean for a parent function to have finished expecting?
When a function finishes executing, its local variables and scope are typically destroyed or garbage collected. However, if there are inner functions (child functions) defined within the parent function, and those inner functions have been returned or are still in scope elsewhere in the program, they can maintain references to the variables in the parent function's scope. This is what creates a closure.
So when we say, "Closure, is a function that has access to the parent scope, even after the parent function has closed," What do we mean?
This means that the inner function maintains a reference to the variables and parameters of the outer function's scope, allowing it to access and manipulate them even after the outer function has completed execution and its local variables should technically be out of scope.
Example
Consider the following scenario:
function outerFunction() {
let outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const innerFunc = outerFunction();
innerFunc(); // Output: I am from the outer function
In this example, outerFunction
defines a variable outerVariable
and also declares an inner function innerFunction
that logs the value of outerVariable
. innerFunction
is then returned from outerFunction
.
Now, when outerFunction
is called and assigned to innerFunc
, it actually returns innerFunction
. But what's interesting is that even after outerFunction
has finished executing and its execution context has been destroyed, innerFunction
still retains access to the variables within its parent scope (i.e., the scope of outerFunction
).
This behavior is what we refer to as closure. The inner function (innerFunction
) has access to its parent function's scope (lexical scope), even after the parent function (outerFunction
) has completed execution and been removed from the execution stack.
To understand this better, let's break down the process:
When
outerFunction
is called, a new execution context is created with its own scope chain.Inside
outerFunction
,innerFunction
is defined, which creates a closure over theouterVariable
.When
innerFunction
is returned fromouterFunction
and assigned toinnerFunc
, it maintains a reference to its lexical environment, which includes theouterVariable
.Later, when
innerFunc
is invoked, it still has access to theouterVariable
because of the closure created during its creation.
Why do you need to understand the concept of closure?
Closure is important in JavaScript because it enables encapsulation, data privacy, and the management of asynchronous operations. With closures, you can create private variables and functions, control access to sensitive data, and maintain the integrity of your code. Closures are crucial for managing asynchronous operations, implementing callbacks, and event handling. They also allow for the dynamic generation of functions and provide a powerful tool for building modular and maintainable code. Understanding closures is essential for writing clean, efficient, and secure JavaScript applications.
Thank you βΊοΈ for taking the time to read. If you're interested in exploring similar topics further, I invite you to connect with me on LinkedIn and Twitter.
LinkedIn: https://www.linkedin.com/in/garuba-abdul-azeez-713273167/
Twitter: https://x.com/devAzeezjim?s=09
ππΌππΌππΌ