'closure' is the combination of a function bundled together with references to its surrounding state (Lexical Environment).
Before we move any further, few things to be aware of in order to understand Closures are:-
1- Execution Context
2- Call Stack
3- Scope Chain
The Execution Context.
There are two types of Execution Context:-
1- Global Execution Context (Global EC )
2- Local Execution Context (Local EC )
const name = 'Anup Verma' function callMe(a,b){ let x = 5; console.log('params :: ',a,b,'name :: ',name ,'x :: ',x); } callMe(2,3);
Global and Local E.C for the above snippet would look like:-
NOTE :
The Local E.C. of a function contains information regarding its “Arguments”, “this” keyword, and “variables” declared inside it.
But , in case of an Arrow Function and Anonymous function , 'this' keyword and 'Arguments' are NOT present.
The Call Stack.
The place where all the Magic Happens.
The call stack is where each and every execution context is placed in the form of a stack and is executed and “popped out” once it is done executing.
Consider the following example.
const counting = function(){ let count = 0; return function(){ count++; console.log('count :: ', count); } } const counter = counting(); counter(); //count :: 1 counter(); //count :: 2 counter(); //count :: 3
The Call Stack and the Execution contexts work together.
As you can see from the bottom two images , even though the counting function is no more present in the call stack , then too the "counter function" has the access to the variables in the Environment in which it was created (i.e counting()).
Closures.
Any function always has the access to the variable environments of the Execution Context in which the function was created, Even after that Execution context is Gone.
“COUNTER()” FUNCTION WAS BORN IN THE EXECUTION CONTEXT OF ‘COUNTING()’ FUNCTION , HENCE THIS ‘COUNTER()’ FUNCTION WILL GET ACCESS TO THE VARIABLE ENVIRONMENT (I.E “COUNT” )
What is Closure?
Closure is this Variable Environment Attached to the function , exactly as it was at the time and place when the function was created and the scope chain is ‘Preserved’ through this closure.
Thanks to this ‘closure’ a function does not lose connection to variables that existed at the function’s birthplace.
Although this is one of those topics that people tend to forget, here are some intuitive examples/analogies to help you understand what closures are all about.
Informal Definition(s)
A closure gives a function ‘Access’ to all the variables of its parent function , even after the parent function has returned. The function keeps a “reference” to its outer SCOPE , which “preserves” the scope chain throughout.
It’s like a person who doesn’t lose connection to their HOME-TOWN, in this analogy,
Person -> Function
Home town -> Parent Scope
PERSON — — —> CONNECTION — — —> HOME-TOWN( — — →VARIABLES)
And the person does not lose connection to the variables stored in its parent scope i.e. home town.
CONCLUSION
We don’t have to create “closures” Manually, this is something JavaScript does completely Automatically, Also there is no way we can access these ‘closed-over’ variables explicitly i.e. because “A Closure is NOT a tangible JavaScript Object.”