This content originally appeared on Telerik Blogs and was authored by Chinedu Imoh
A closure is the combination of a function bundled together with references to its surrounding state. It’s a simple and useful technique once you understand it.
Closures are one of the most widely discussed and still confusing concepts in JavaScript—and also one of the most common questions you are likely to encounter in an interview when applying for a JavaScript position. As the title says, I will be making the topic clearer and easier to understand.
What Is a Closure?
A closure is a feature in JavaScript where an inner function has access to the scope (variables and parameters) of its outer functions, even after the outer function has returned.
Note: Scope in JavaScript refers to the current context of code, which determines the accessibility of variables to JavaScript. The two types of scope are local and global:
- Global variables are those declared outside of a block
- Local variables are those variables declared inside a block
In other words, a closure gives you access to the following scope:
- Access to its scope; variables defined within its block of code
- Access to the outer function’s variables
- Access to the global variables
Here’s is a simple example of a closure in JavaScript:
// Defining the outer function.
function enclosing() {
var x = "outer";
// Defining the inner function.
function inner() {
var y = "inner";
console.log(x, y)
}
return inner;
}
// invoking enclosing returns the inner function.
var a = enclosing()
x()
We defined two functions:
- The outer function
enclosing
with a variablex
that returns a nested function - The nested function
inner
with a variabley
that logs both the value of its variable and that of its parent function
Note: A function can return another function in JavaScript. A function that is assigned to a variable is called function expression. And, the
return
statement does not execute the inner function—a function is executed only when followed by()
—but rather thereturn
statement returns the entire body of the function.
This is a step-by-step walkthrough of the flow of execution:
- After invoking
enclosing()
at line 13, variable x is declared and assigned a value. - Next is the declaration of the function
inner
. - The
return inner
returns the entire body of the functioninner
. - The contents returned by the return statement are stored in
a
. Thus,a
will store the following:
function inner() {
var y = "inner";
console.log(x, y)
}
- Function
outer()
finishes execution, and all variables within the scope ofouter()
now no longer exist.
Note: The lifespan of a variable defined inside a function is the lifespan of the function execution.
What this means is that in console.log(x, y)
, the variable x
exists only during the execution of the enclosing()
function. Once the enclosing
function has finished execution, the variable x
no longer exists.
Now, we know that the function enclosing
returns a function, and that gets stored in variable a
.
- Since
a
is a function, we execute it on line 14. When we executea()
, we are essentially executing theinner
function. Let us examine step-by-step what happens whena()
is executed:
a. Variabley
is created and assigned a value.
b. Next, it logs to the console the value of parent function variablex
and its local variabley
.
Now, you may be asking, “How does the function inner
have access to its parent function variable x
, since its parent function has finished execution long before we invoked a()
and we noted earlier that the lifespan of a variable defined inside a function is the lifespan of the function execution?”
The answer to this question is …
Closures!
The function inner
has access to the variables of the enclosing function due to closures in JavaScript. In other words, the function inner
preserves the scope chain of function enclosing
at the time it was executed, and thus can access the parent’s function variables.
The function inner
had preserved the value of its parent function variable x
when the parent function was executed and continued to preserve (closure) it.
It now refers to its scope chain and notices that it does have the value of variable x
within its scope chain since it had enclosed the value of x
within a closure at the point when the enclosing()
function had executed.
Thus, that is how JavaScript can remember not only the value but also the variable of the parent function after it has long finished execution.
When to Use a Closure?
Closures are useful in hiding implementation details in JavaScript. In other words, it can be useful to create private variables or functions.
The following example shows how to create private functions and variables.
var name = (function() {
var username = "";
function setName(val) {
username = val;
return username
}
return {
set: function(val) {
return setName(val);
}
};
})();
console.log(name.set("John Doe"))
In the above example, set
becomes a public function because it is included in the return object, whereas function setName
becomes a private function because it is not returned and can only be used internally within the parent function.
Summary
Hopefully these step-by-step explanations helped you understand the concept of closures in JavaScript.
This content originally appeared on Telerik Blogs and was authored by Chinedu Imoh
Chinedu Imoh | Sciencx (2021-12-23T10:41:01+00:00) Demystifying Closures in JavaScript. Retrieved from https://www.scien.cx/2021/12/23/demystifying-closures-in-javascript-2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.