Introduction
To understand closures, we first have to understand Lexical Environment and Scoping.
Lexical Environment
The Lexical Environment refers to the context within which JavaScript code is executed. This context includes where the code is written and its surrounding environment.
Consider the following example:
function myFunction() {
let a = 1;
function innerFunction() {
console.log("Hello", a);
}
innerFunction();
}
In this example, innerFunction
can access the variable a
because it's inside myFunction
, which contains innerFunction
. The lexical environment includes all variables and functions that can be reached in the current area and its parent scopes.
Lexical Scoping
Lexical Scoping means that a variable's scope depends on where it is in the source code.
Here's an illustration:
function myFunction() {
let a = 1;
function innerFunction() {
console.log("Hello", a);
}
return innerFunction;
}
const returnedFunction = myFunction();
returnedFunction(); // Accesses `a` even outside its defining scope
In this example, innerFunction
is executed outside of myFunction
, yet it keeps access to a
. This happens because of closures.
Closures Explained
When myFunction
is called, it creates a new environment that has a
. By returning innerFunction
, it keeps access to myFunction
's environment. This ongoing access is what we call a closure.
A closure happens when a function can remember and use its original scope, even if it's run outside of that scope. This means innerFunction
keeps the scope of myFunction
, letting it access a
no matter where innerFunction
is called, even in another file.
This isn't possible in all programming languages.
Practical Use Cases
Closures are not just a theoretical aspect of JavaScript, they have practical use cases:
Data Encapsulation: Closures allow for private variables that cannot be accessed directly from outside the function.
Factory Functions: They can be used to create function factories that can create multiple instances of similar functions, each with access to private variables.
Event Handlers and Callbacks: Closures are widely used in event handlers and callbacks, where specific variables need to be accessed.