Google

Jan 11, 2012

JavaScript Interview Questions and Answers: Closure



We earlier saw that JavaScript functions are like objects, and can be passed as arguments from one function to another, can be assigned to a variable, etc.


Q. What do you understand by the term closure in JavaScript?
A. Whenever you have a function within a function, a closure is used. A closure is like local variables for functions. Let's look at an example.


var calculate = function(x) {     //outer function    
     var myconst = 2; 
     myconst++; //myconst is now 3
     return function(y) {           //inner function
         return x + y + myconst;    // has visibility to parent variable 'myconst'
     }; 
        
}  

//closure 1: each function call has its own closure
var plus5 = calculate(5);       // plus5 is now a closure to the inner function, 
                                // and has access to the outer function's values
                                // when function call exits myconst = 3 and x = 5 

console.log(plus5(3));          // returns 11  i.e. x=5, y=3, myconst=3 


//closure 2: each function call has its own closure
var plus7 = calculate(7);       // plus7 is now a closure to the inner function, 
                                // and has access to the outer function's values
                                // when function call exits const = 3 and x = 7 



console.log(plus7(4));          // returns 14  i.e. x=7, y=4, const=3 



In general, when you exit out of a function, all the local variables (e.g.myconst and x) go out of scope. As per the above example, you could think that a closure is created on entry to the outer function, and the local variables are added to the closure. The closure is stored to the variable like plus5, plus7, etc and invoked by passing the value for "y". Each function call will have its own closure (e.g. plus5 and plus7)


So, a closure means the local variables of the outer function is kept alive after the function has returned.


Example 2:

function count() {
    var num = 0;    //local variable that ends up within enclosure
    var display = function() {  // the variable "display" is also part of the closure
       console.log(num++);  
    }
    
    num++; //the num is 1
    
    
    return display;
}


var  increment = count(); // num is 1

increment();    //Can be assigned to a button.
                //every time invoked displays number starting from 2, and incrementing it by 1 as in 2,3,4,etc.



In the above example, the variable "display" is also inside the closure and can be accessed by another function that might be declared inside count() or it could be accessed recursively within the "display" function itself.

Q. What will be the out put of the following JavaScript when you click on the "click-me" button that invokes the function testList()?

<form id="evaluate1">
    <input type="button" value="click-me"  onclick="testList()"/>  
</form>

function listCars (list) {
   var listOfFns = [];
   //construct and store functions
   for(var i=0; i<list.length; i++) {
      listOfFns.push(function() {console.log("The car is: "  + list[i])});
   }

   return listOfFns;
}


function testList() {
    var listOfFns = listCars(["Toyota", "Honda", "Ford", "Mazda"]);   //Line A
    //invoke the functions by looping through             
     for(var i=0; i<listOfFns.length; i++) {                          //Line B 
        listOfFns[i]();
     }

}



A: The output will be "The car is: undefined". This is because when the closure is created in "Line A" the the value of the variable "i" in function listCars(…) is 4, which is the exit condition for the for loop. Now in Line B, when you try to execute the inner function

function() {
   console.log("The car is: "  + list[i]);
}


Since the value of i in the closure is 4, the list only has 4 elements with indices 0,1,2, and 3, the index 4 is undefined. That list[4] is not defined. This is a general gotcha when working with closure and arrays.



Points to remember:

  • Closures are created every time you create a function in a function.
  • Closures give you access to variables that are defined in the parent function, and all of its parents.
  • Closures will help you keep your code clean and easy without having to use the global variables.


//outer function
function createTimer() {
       // inner function invoked from the outer function using closure
       function alertTimerId() {
            // the timerId is a local variable from the outer function, which is in the closure
            alert("The timer id is " + timerId);
       }
     
       //invoke the inner function from the outer.
       var timerId = window.setTimeout(alertTimerId, 1000); // alerts after 1000 ms or 1 second.
}
     
createTimer();




The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds.

setTimeout(code,millisec,lang)




code (Required) -- A reference to the function or the code to be executed
millisec (Required) -- The number of milliseconds to wait before executing the code
lang (Optional) -- The scripting language: JScript | VBScript | JavaScript



Q. What is a "module pattern"?
A. The module pattern emulates familiar OO concepts of private and public methods and attributes. It does so by utilizing closures to "hide" elements from the global scope. The public behavior is achieved by returning the private members from your object. Public functions can access the private members.

Global variables are evil, and Douglas Crockford has been teaching a useful singleton pattern for avoiding global variables. The "module pattern" creates an anonymous function, and executes it immediately. All of the code that runs inside the function lives in a closure, which provides privacy and state throughout the lifetime of our application.

(function () {
 // all vars and functions are in this scope only
 // still maintains access to all globals
}());




So there is a difference between function declartion and function expression. The identifier (e.g print) is optional for the function expression. Here is an example of function expression.
 

//function declaration
function print(msg){
   alert(msg);
 }


 
//function expression
(function (msg){
   alert(msg);
 }
)('Hello World');


Note that the () around the anonymous function is required by the language, since statements that begin with the token function are always considered to be function declarations. Including () creates a function expression instead. Here is an example

var  myProject = {};   //some namespace



myProject.myModule = (function () {



 //"private" variables:

 var myPrivateVar = "myPrivateVar can be accessed only from within myProject.myModule.";



 //"private" method:

 var myPrivateMethod = function () {

  console.log("myPrivateMethod can be accessed only from within myProject.myModule");

 }



 return  {

  myPublicProperty: "myPublicProperty is accessible as myProject.myModule.myPublicProperty.",

  myPublicMethod: function () {

   console.log("myPublicMethod is accessible as myProject.myModule.myPublicMethod.");



   //Within myProject.myModule, I can access "private" vars and methods:

   console.log(myPrivateVar);

   myPrivateMethod();



   //access public members using "this" as the native scope of myPublicMethod is myProject.

   console.log(this.myPublicProperty);

  }

 };



}());





function test() {

    alert(myProject.myModule.myPublicProperty); //defined -- accessing public property

    myProject.myModule.myPublicMethod();        //defined -- accessing public method

    alert(myProject.myModule.myPrivateVar);     //undefined -- accessing private property -- NOT OKAY

    myProject.myModule.myPrivateMethod();       //myProject.myModule.myPrivateMethod is not a function -- accessing private method -- NOT OKAY

}

Pros and Cons
Pros:
  • Easy to pick up for software engineers, as this emulates a familiar pattern
  • Clean encapsulated code
  • Private methods and attributes
Cons:
  • Dependent on ordering
  • Accessing public methods requires repeating the parent object name
  • Lack of full support for private members


The Revealing Module Pattern is an extension of the Module Pattern, the main difference being that all methods and attributes are declared as private and optionally exposed in the return of the object. In the process of exposing the methods/attributes we additionally have the option of providing a different name for the exposed reference.


var  myProject = {};        //some namespace

myProject.myObject = (function() {
    var myPrivateVar = "private";
    var myPrivateFunction = function() {
     console.log("private function is called");
        return myPrivateVar;
    }
 
    return {
        publicFunctionName: myPrivateFunction
    }
}())


function test() {
    myProject.myObject.publicFunctionName();       //defined -- accessing public method
    myProject.myObject.myPrivateFunction();        // myProject.myObject.myPrivateFunction is not a function -- NOT OKAY
}



Pros and Cons

Pros:

  • Easier to read structure
  • All methods/attributes are referenced in the same way
  • Ability to expose members with a different name

Cons:

  • Lack of full support for private members


You can learn more about the JavaScript design patterns at Essential JavaScript Design Patterns For Beginners, Volume 1.-- Addy Osmani.


More JavaScript Q&A

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home