loading...
Cover image for The walk: On Closures

The walk: On Closures

aasthatalwaria profile image Aastha Talwaria ・3 min read

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.


Alt Text
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.

Posted on by:

Discussion

markdown guide