Master Closures in JavaScript

Posted By : Ankit Uniyal | 30-Apr-2018

In this blog, we will discuss Closures in JavaScript, which is a very important concept in JavaScript.

In JavaScript, variables defined outside the function are automatically available inside to the function because JavaScript used lexical scoping means an inner variable is not accessible outside whereas outside variable can be accessed inside.

var passed = 3;

var addTo = function() {
    var inner = 2;
    return passed + inner;
}
console.dir(addTo());  

 

As, closures in JavaScript is basically an inner function that has access to the outer function scope, as it is still accessible even the outer function has returned the control.A Closure basically makes the inner function private.

If you look at above code, you can see that addTo function can access the outer variable named passed.

 

Let's take an another example which represnts closures in JavaScript.

function displayName(firstName, lastName) {

    var name = "your name";

    function displayFullName() {

        return name + firstName + " " + lastname;

    }

    return displayFullName();

}

displayName("Ankit", "Uniyal");
        

Closures can access outer function variables even after outer function has return the value.When JavaScript functon executes, it uses the same scope chain that is in effect when it was created, it means outer function variables can be accesed after function returns by the inner function.

 

Since closures have access to updated values of the outer function’s variables but this can lead to some errors when the outer function's variable changes withinh loop. Like for example below :

 

function createId(dataResults) {

    var i;
    var uniqueId = 100;
    for (i = 0; i < dataResults; i++) {
        dataResults['id'] = function() {
            return uniqueId + i;
        }
    }
    return dataResults;
}

var actionValues = [{
    'name': "Ankit",
    'id': 0
}, {
    'name': "Nitin",
    'id': 1
}, {
    'name': "Rohit",
    'id': 2
}];

var createIdForData = createId(actionValues);

var firstId = createIdForData[0];

console.log(firstId.id()); //103
        

 

Now in the above code snippet, when anonymous functions are called, the value of i is 3. The number 3 was added to the uniqueID to create 103 for all the ID's. So, at every index position in the returned array get id = 103, instead it should be 100, 101, 102.

 

As, this is because, the closure has access to outer function’s variables by reference, not by value. As, we can access the updated variable with the closure, the above code accessed the i variable whenever it gets changed, but the outer function runs the entire loop and only returns the last value of i, which is 103.

 

But this can be handled using Immediately Invoked function Expression (IIFE) which is explained below :

 

function createId(dataResults) {

    var i;
    var uniqueId = 100;
    for (i = 0; i < dataResults; i++) {
        dataResults[i]['id'] = function(j) { // the j parametric variable is the i passed in on invocation of this IIFE
            return function() {
                return uniqueId + j; // every iteration of for loop passes the current value of i to this IIFE and it saves the correct value to the array?
            }() // On adding () at the end of this function, it executed immediately and returning just the value of uniqueId + j.
        }
    }
    return dataResults;
}

var actionValues = [{
    'name': "Ankit",
    'id': 0
}, {
    'name': "Nitin",
    'id': 1
}, {
    'name': "Rohit",
    'id': 2
}];

var createIdForData = createId(actionValues);

var firstId = createIdForData[0];

console.log(firstId.id); //100

var secondId = createIdForData[1];
console.log(secondId.id);
        

Thanks.

About Author

Author Image
Ankit Uniyal

Ankit has knowledge in Javascript, NodeJS, AngularJS and MongoDB also have experience in using AWS Services.

Request for Proposal

Name is required

Comment is required

Sending message..