Closures
in JavaScript is a feature where an inner function can access the outer function's variables. The concept of closures revolves around the term :
lexical scope or scope chain
The word lexical
refers to the fact that lexical scoping uses the location where a variable is declared within the source code to determine where that variable is available. Nested functions have access to variables declared in their outer scope.
So, we can say that an inner function
has three scope chains:-
- variables defined in its own scope
- variables defined in outer function’s scope
- and the global variables
Let's understand this by looking at an example.
function getNameFunction(){
var initialWord = 'The ';
function getName(){
var title = 'Walk';
return initialWord+title;
}
return getName;//returning the function
}
var output = getNameFunction();//outut will carry getName function ref.
In the above example, we have two functions getNameFunction
(outer function) and getName
(inner function).
'getNameFunction' has local variable named as 'initialWord' and a function 'getName' and returns 'getName' which is actually a function ( Note: 'getNameFunction'is not executing the function, it simply returning the body of the function 'getName' ). Now after returning the 'getName', all the variable in the scope of the outer function no longer exists.
Wait, Did you read that? the variable no longer exists.
Then how will our getName
(inner function) function survive in the outer world as its dependent on the variable of the outer function (initialWord
)?
Don't worry! JavaScript makes this function survive with the help of closures.
The lifespan of a variable defined inside of a function is the lifespan of the function execution. In this case, output
is a reference to the instance of the function getName()
created when getNameFunction()
is invoked. The instance of getName
maintains a reference to its lexical environment, within which the variable initialWord
exists. Witness this by using below mentioned code
output();//returns: The walk
What if the inner function changes the outer function's variable value.
Will that make any difference when we call the outer function again. Let's dig more into closures with next example.
function getFunctionByType(type){
var initialValue = 5;//initial value
function getValue(){//inner function
if(type === 'increment'){
return ++initialValue;//changing the value of variable defined in outer function scope
} else if(type === 'decrement') {
return --initialValue;//changing the value of variable defined in outer function scope
} else {
return initialValue;//changing the value of variable defined in outer function scope
}
}
return getValue; //returning inner function
}
var incrementFunction = getFunctionByType('increment');
var decrementFunction = getFunctionByType('decrement');
In the above example, the outer function has two local variables type
and initialValue
and a function getValue
which is using the variables of its surrounding function getFunctionByType
and changing their values.
Let's invoke incrementFunction
and decrementFunction
.
incrementFunction();//returns 6
decrementFunction();//returns 4
Is this what you expected. If no, then don't worry, I will explain.
When we invoked getFunctionByType
for the first time, the function creates the fresh variable and initialize its value. And those values are accessed by the getValue
instance function stored in incrementValue. That instance then maintains the reference of its lexical environment, within which the variable type
and initialValue
exists and outer scope vanishes.
For the second time invoke, getFunctionByType
creates its local variable again fresh with the mentioned initial values and creates the function getValue and returns it.
Which means, the two instances of getValue
have a separate world. They don't share anything. Both of them is having their own lexical scope and outer function's variables. If one changes the value of its outer function, that will not affect the values of second.
How JavaScript maintains it.
The answer is by maintaining the scopes. First of all, when js encounters a variable it looks for that variable in the inner scope. If that is not present in the inner scope it goes for its outer scope. To check for the above example, you can see all the properties of the getName()
instance by using console.dir(incrementFunction)
and console.dir(decrementFunction)
.
//incrementFunction whose properties should be output
console.dir(incrementFunction);
NOTE: console.dir()
is the way to see all the properties of a specified JavaScript object in the console by which the developer can easily get the properties of the object.
So, by expanding the properties, in Scopes, you will see Closure where the function name is given(getFunctionByType) and its variables are present(type, initialValue).
So, this was all about Closures from my side.
If you want to ask or share anything about closures, and this post then start a discussion (in discussion box mentioned below) or you can hit me up at aastha.talwaria29@gmail.com.
And if you have any suggestions for my next article then please let me know.
Thanks for reading.
Top comments (0)