The first thing that we need to know about closures is that a closure is not a feature that we explicitly use. So we don't create closures manually, like we create a new array or a new function. So a closure simply happens automatically in certain situations, we just need to recognize those situations.
Most of the times when we run code in other languages we can not access variables outside of a function inside of that function, that is just not always possible in other languages but it is possible in javaScript and it is what we call a closure.
Let's Start with this simple code:
let a = 1;
function print() {
console.log(a);
}
print();
It printed number 1. This is actually a closure.
We have an inner scope of the function:
function print() {
console.log(a);
}
And this inner scope is accessible in variable a
which is inside the outer scope.
Now, if we take a
and reassign it to 2
before we call print()
function, now it prints out number 2
.
let a = 1
function print() {
console.log(a);
}
a = 2
print();
This is because this print()
takes whatever the most recent value of a
is, whenever we call print()
.
But usually closures are defined as functions inside of other functions;
function print(variable) {
return function func(variable2) {
console.log(variable);
console.log(variabl2);
}
}
we are calling function print
which takes a variable and is returing a brand new function which is going to log out a variable from print
as well as a variable2 from func
function.
Now:
function print(variable) {
return function func(variable2) {
console.log(variable);
console.log(variable2);
}
}
let a = print(1);
This is doing as calling function print()
, so a
is a new function. Now we call a()
and we pass to it 2
function print(variable) {
return function func(variable2) {
console.log(variable);
console.log(variable2);
}
}
let a = print(1);
a(2);
a(2)
will call function print(variable)
which is going to log out variable
which is 1
and then is going to log out variable2
which we passed into function func(variable2)
which is a(2)
. Result is :
1
2
We have an inner scope that has access to variable2
and also has access to variable
from the outer scope of the print(variable)
. Now we add C
variable:
function print(variable) {
let c= 3;
return function func(variable2) {
console.log(variable);
console.log(variable2);
console.log(c);
}
}
let a = print(1);
a(2);
Result:
1
2
3
Even if the c
is defined out of the function func
, since JavaScript is able to read outside of inner scope, we have inner scope:
return function func(variable2) {
console.log(variable);
console.log(variable2);
console.log(c);
}
}
that is in outer scope:
function print(variable) {
let c= 3;
return function func(variable2) {
console.log(variable);
console.log(variable2);
console.log(c);
}
}
let a = print(1);
a(2);
it is able to access variable c
as well as variable
in print(variable) and variabl2
which is inside the current scope.
Another Example:
let myName = "Pinkey";
function printName() {
console.log(myName);
}
printName();
So this variable( myName) that is external to printName()
, is actually available internally inside printName()
, myName is a global variable essentially and it is available inside printName()
.
We have the entire javaScript file that is one scope and then our function is another scope, so every scope has access to everything outside of it's scope.
Now we change the name;
let myName = "Pinkey";
function printName() {
console.log(myName);
}
let myName="pegah"
printName();
What is happening? it is taking the current live value of that name
let myName = "Pinkey";
function printName() {
console.log(myName);
}
let myName="pegah";
printName();
myName= "Parwane";
printName();
It constantly going with whatever the most recent of that value is.
Most people think of closures as functions inside of other functions:
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log("Outer Variable:" + outerVariable);
console.log("Inner Variable:" + innerVariable);
}
}
let newFunction = outerFunction("outside");
newFunction("inside");
Here we have a function called outerFunction
and that function is returning another function inside of it called inner function and then we are calling down here outer function with variable outside .
Now we are getting a new function and then lastly we are calling that new function with the variable inside.
When we fist call outerFunction
we have this outervariable
which we set to outside and then we have innerFunction
that gets returned and the reason we are able to access this outervariable
inside of **innerFunction` is closures.
outerfunction
runs and outervariable
is only available inside of innerfunction
, now we remove this code:
newFunction("inside")
and nothing prints out and that's because we call
outerfunction
here in
let newFunction=outerFunction("outside");
And it executes all of the code and then it's done executing
and outervariable
is no longer accessible for example we can not log out the outervariable
console.log(outervariable);
So how the innerfunction
is able to access outervariable
even after it is done being executed, outervariable
has gone out of scope and that is where closures come.
Innerfunction
is essentially saying: I am inside outerfunction
, it has outervariable
so i am going to save outervariable
and even the function that defined this variable is no longer available, i am still going to keep track of the outervariable
.
`
function outerFunction(outerVariable) {
let outer2 = "hi";
return function innerFunction(innerVariable) {
console.log("Outer Variable:" + outerVariable);
console.log("Inner Variable:" + innerVariable);
console.log(outer2);
}
}
let newFunction = outerFunction("outside");
newFunction("inside");
`
outer2
is inside of scope but out of innerfunction
, outerfunction
is contained inside innerfunction
so everything in the outer function is available inside the innerfunction
since in javaScript anything on the inside has access to the things on the outside of it's scope essentially it has access to it's parent scope and it's parent parent scope and so on.
All we need to know about closures is that when we have a function defined inside of another function that innerfunction
has access to the variables and the scope of the outer function even if the outer function finishes executing and those variables are
no longer accessible outside that function.
Let's jump to another example:
securebooking()
will return a new function. And what we do in this function is to update the passengerCount
variable.And then let's just log the new passengerCount
to the console.And now let's call the secure booking function and then store the result in a variable called Booker
.
So let's analyze in detail :
Now, before we start running the secure booking function, our code is running in the global execution context. And in there, we currently only have this secure booking function. And so we can also say that the global scope now contains secure booking.Then when secure booking is actually executed, a new execution context is put on top of the execution stack. Each execution context has a variable environment, which contains all its local variables. In this case, it only contains the passengerCount
set to zero.
In the next line of the secure booking function, a new function is returned and it will be stored in the Booker variable. So the global context now also contains the Booker variable. And now what else happens when the secure booking function returns? It's execution context pops off the stack and disappears. So the secure booking function has done it's job and has now finished execution.
Now let's see closure in action:
let's call booker()
three times
How can the Booker function update this passengerCount
variable that's defined in a secure booking function that actually has already finished executing?!
a closure
Now let's run the booker()
Booker()
is located in the global scope. The first thing
that's gonna happen is that a new execution context is created and put on top of the call stack and the variable environment of this context is emptied simply because there are no variables declared in this function.
So how will the Booker function access the passengerCount
variable? The secret of the closure
Any function always has access to the variable environment of the execution context in which the function was created. Now, in the case of Booker
, this function was created. It was born in the execution context of secure booking, which was popped off the stack previously, So, therefore the Booker function will get access to this variable environment, which contains the passengerCount
variable. And this is how the function will be able to read and manipulate thepassengerCount
variable. And so it's this connection that we call closure.
Top comments (0)