Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

JavaScript Closures

Tags: function outer

Closures allow JavaScript programmers to write better and concise code. A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain. The closure has three scope chains: it has access to its own scope (variables defined between its curly brackets), it has access to the outer function’s variables, and it has access to the global variables. The inner function has access not only to the outer function’s variables, but also to the outer function’s parameters. Note that the inner function cannot call the outer function’s arguments object, however it can call the outer function’s parameters directly. A closure is created by adding a function inside another function.


function getNumbers() {
    var numbers = [3, 8, 5];
    function filter () { // this closure has access to the numbers variable
	var items = [];
        for(item in numbers) {
            if (item > 6) {
                items.push(item);
            }
        }   
        return items;
    }
    return filter();
}

Closures are also frequently used in jQuery and just about every piece of JavaScript code you read.


$(function() {
    $("#btn").click(function() {
        console.log("btn clicked");
    });
});

Closures have access to the outer function’s variables even after the outer function returns. When functions in JavaScript execute, they use the same scope chain that was in effect when they were created. This means that even after the outer function has returned, the inner function still has access to the outer function’s variables. Therefore, you can call the inner function later in your program.


function createName(firstName) {
    var prefix = "My name is ";
    function addLastName(lastName) {
        return prefix + firstName + " " + lastName;
    }
    return addLastName;
}
	
var name = createName ("John"); //the createName outer function has returned.
name("Smith"); // My name is John Smith

Closures store references to the outer function’s variables; they do not store the actual value. Closures get more interesting when the value of the outer function’s variable changes before the closure is called. And this powerful feature can be harnessed in creative ways, such as this private variables example:


function workerId () {
    var innerId = 1;
    return {
        getId: function ()  {
            return innerId;
        },
        setId: function (newId)  {
            innerId = newId;
        }
    }
}

var wId = workerId(); //the workerId outer function has returned.
wId.getId(); // 1
wId.setId(15); // Changes the outer function's variable
wId.getId(); // 15: It returns the updated workerId variable

Because closures have access to the updated values of the outer function’s variables, they can also lead to bugs when the outer function’s variable changes with a for loop. Thus:


function workerIdCreator(workers) {
    var i;
    var workerId = 100;
    for (i = 0; i < workers.length; i++) {
        workers[i]["id"] = function ()  {
            return workerId + i;
        }
    }
    return workers;
}

var workers = [{name:"Davis", id:0}, {name:"Cullon", id:0}, {name:"Parlour", id:0}];
var createWorkerIds = workerIdCreator(workers);
var davisId = createWorkerIds[0]; 
console.log(davisId.id()); // 103

In the preceding example, by the time the anonymous functions are called, the value of i is 3 (the length of the array and then it increments). The number 3 was added to the workerId to create 103 for all the workerId. So every position in the returned array get id = 103, instead of the intended 100, 101, 102. The reason this happened was because, as we have discussed in the previous example, the closure (the anonymous function in this example) has access to the outer function’s variables by reference, not by value. So just as the previous example showed that we can access the updated variable with the closure, this example similarly accessed the i variable when it was changed, since the outer function runs the entire for loop and returns the last value of i, which is 103. To fix this side effect (bug) in closures, you can use an Immediately Invoked Function.


function workerIdCreator(workers) {
    var i;
    var workerId = 100;
    for (i = 0; i < workers.length; i++) {
        workers[i]["id"] = function (j)  { // the j parametric variable is the i passed in on invocation
            return function () {
                return workerId + j; // each iteration of the for loop passes the current value of i and it saves the correct value to the array
            } () // by adding () at the end of this function, we are executing it immediately and returning just the value of workerId + j, instead of returning a function.
        } (i); // immediately invoke the function passing the i variable as a parameter
    }
    return workers;
}

var workers = [{name:"Davis", id:0}, {name:"Cullon", id:0}, {name:"Parlour", id:0}];
var createWorkerIds = workerIdCreator(workers);
var cullonId = createWorkerIds[1]; 
console.log(cullonId.id()); // 101

Blog Categories

  • General
  • Showcase
  • Technical
  • White Papers


This post first appeared on Shield UI Blogs | Shield UI, please read the originial post: here

Share the post

JavaScript Closures

×

Subscribe to Shield Ui Blogs | Shield Ui

Get updates delivered right to your inbox!

Thank you for your subscription

×