Javascript Jems - Asynchronous Patterns And Closure
Written by Ian Elliot   
Tuesday, 03 June 2014
Article Index
Javascript Jems - Asynchronous Patterns And Closure
The Asychronous Problem and Pattern

If you have ever been kept awake at night worrying about closure then this is for you? You can understand closure, but what is it for? We explain how it can be all so easy and really, really useful. Closure in Javascript was made for asynchronous code and for Ajax in particular.

 

Banner

 

Asynchronous patterns in JavaScript are about to be completely changed because ECMAScript 6 supports promises and thus makes this the way to implement an asynchronous call. Even before ECMAScript 6 lands on sufficient browsers to make it the standard you can use promises either as part of a library like jQuery or as a stand alone implementation. 

Promises are great but there are times when you need something that works in a simpler and perhaps more backward compatible way. There is also the fact that understanding good ways of handling asynchronous calls that are closer to core JavaScript might give you new ideas. 

Closure is usually regarded as an "advanced" feature of Javascript and correspondingly off putting. Sometimes it is introduced as a way of achieving a specific job like creating private variables for methods but this often leaves you with the feeling that while you understand it it isn't clear what more general use it could be. 

The problem with closure isn't that it is difficult to understand it is difficult to see why you might want to use it. 

In fact it really is very simple and very useful.

 

jemsicon

 

What is a closure?

(If you already know about Javascript closure then skip to the next section, The Asynchronous Pattern.)

Put simply closure means that a function has access to all of the variables declared at the same "level" as it in addition to its local variables – even if any enclosing function has terminated.

Think about this basic definition for a moment.

A function normally has access to everything defined at the same scope as it. For example:

function myFunction(){};

has access to any variables it declares plus all the global variables.

function myOuterFunction(){
 var a=123;
 function myInnerFunction(){
  ...  

 };
}

Then myInnerFunction has access to all of its local variables plus any that have been declared in myOuterFunction such as a and of course any global variables.

Everything that should be accessible from with in it is accessible from within it. No shocks or surprises yet.

The part of the definition that is surprising is that it still has access to "everything" after that everything has in principle been destroyed because the myOuterFunction has terminated and all of its variables should no longer exist.

This is a natural consequence of functions in JavaScript being "first class". Functions in JavaScript are objects and they have a lifetime that isn't necessarily directly connected to where they are defined. You need to recall that an object in JavaScript exists for as long as there is a reference to it. Once all of the references have been removed then the garbage collector will eventually free up the memory that the object occupies.

This simple fact means that a Function object can exist well after the code that created it has stopped running and its Function object been garbage collected.  

When ever a function, more properly a Function object is created then it captures all of the variables that were defined along with it, and hence are in scope and it has access to these variables as long as it, the Function object, exists.

If this wasn't the case the function would behave differently at different times in the programs execution. This way a function always works in the same way irrespective. 

Three Ways To Make A Closure

A closure is formed when a function has a reference to it that persists beyond the natural life of the function.

Exactly how can this come about?

The only way that this can happen is if there is a reference to the function from some other part of the program which is still active. That is, the block of code in which the function is defined terminates and so all of the variables it declared no longer exist, but the function is kept alive because there is a reference to it that lives on in some other part of the program.

Roughly speaking there are three general ways that this can happen but there are lots of minor variations on these ways. 

a) Return A Function

One of the most common ways to make a closure is to return a function as the result of another function.

Let's look at the simplest possible example:

function MyOuterFunction(){
 var a=123;
 function MyInnerFunction(){
  alert(a);
 }
 return MyInnerFunction;
}

If you read through MyOuterFunction you can see it declares a local variable which it sets to 123. It then defines a local function MyInnerFunction which simply displays the value of a. The inner function has access to the variable a because it is local to MyOuterFunction.

So far nothing odd is going on. However, when MyOuterFunction comes to an end it returns a reference to MyInnerFunction.

So if you now write:

var f=MyOuterFunction();
f();

you will see closure in action.

The first line stores a reference to MyInnerFunction returned by MyOuterFunction in f. The final line uses the function invocation operator i.e. () to call the function that f is set to. In this case it is MyInnerFunction and this displays an alert box with 123, the value of a in it.

b) Assign A Function To A Global Variable

You can create the closure by simply assigning the function to a global variable if you want to. The only real change to the previous example is that you now have to make use of a function expression to define the function:

function MyOuterFunction(){
 var a=123;
 this.f=function (){
  alert(a);
 }
}

MyOuterFunction();
f();

This works in exactly the same way as the previous example except that now the inner function is referenced by the global variable f. Recall that in a function that isn't being used as a method this references the Global object. 

One small modification that you often see is to invoke the outer function immediately:

(function MyOuterFunction(){
 var a=123;
 this.f=function (){
  alert(a);
 }
})();
f();

 

c) Incorporate The Function In A Longer Lived Object

Basically this is just a way of getting a longer lived reference to the function. For example you can use a timer:

function MyOuterFunction() {
 var a = 123;
 setTimeout( function() { alert(a); },5000);
};
MyOuterFunction();

In this case the timer keeps a reference to the function and this persists after MyOuterFunction has finished so a closure is created. When the function is executed five seconds later it still has access to a. 

This is in fact an example of  setting a function as an event handler for a DOM object. The setTimeout method belongs to the Window object. 

You can use other DOM objects in the same way as long as they are part of the active DOM tree. In this case the DOM object isn't garbage collected by the JavaScript engine because the DOM has a reference to it - i.e. where it fits into the DOM tree. In general DOM objects are never garbage collected while they are part of the DOM tree.

More of this example later. 

 

Banner

<ASIN:0596805527>

<ASIN:193398869X>

<ASIN:0137054890>

<ASIN:1449381871>

<ASIN:1430230541>

<ASIN:0470526912>



Last Updated ( Tuesday, 03 June 2014 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.