For everything there is a function!

JavaScript as you know is a functional language, meaning that functions are treated as ‘first class’ objects. They can be used as plain old functions, assigned to variables, passed in a parameters, created on the fly, extended and act and work as objects.

A PHP programmer who has been treating JavaScript as a supplementary language finds this variety of function construction and invocation a bit frustrating. To ease the pain here is a short essay.

There are three common ways of defining and invoking a JavaScript function.

The most common is the ‘Named function’ that we all know and love.

    //named or declarative function
    function myFn(someVar){
        alert('myFn executed - ' + someVar); 
   };
   
   //To invoke
    myFn(77);

The output is as expected: myFn executed – 77

Just to whet your appetite this simple function can have properties and methods and can be augmented using the prototype property.

The next method of declaring a function is as an expression or literal. Consider the following example:

//function expression or function literal
   var myFn2 = function(someVar){
      alert('Function executed - ' + someVar); 
   };
//to invoke
   myFn2(88);

The output in this case will be ‘Function executed – 88’

As you can see there is nothing special about this except that the variable myFn2 holds the reference to the function.

The third way of defining and invoking is using the constructor pattern.

//using the constructor
   function myFn3(someVar){
      alert('Function executed - ' + someVar); 
   };
//to invoke
   var myFnInstance = new myFn3(99);

The output in this case will be ‘Function executed – 99’

But, all said and done, these various function incarnations begs us the question…where should we be using each type, how and why?

One of my favorites is to pass a function as a parameter. This is something very powerful and its applications are only restricted by your imagination. Consider the following example:

 //Main function which accepts a function reference as an argument
   var myMainFn = function(someFunc){
      someFunc();
   };
  
   //A simple function expression
   var myFn1 = function(){
      alert('myFn1 executed');
       
   };
   
   myMainFn(myFn1);

The output is ‘myFn1 executed’!

Think about it. A main dispatch function which receives a function reference as an argument. We now have a dynamic function dispatch table.

My next favorite type is ‘Returning Functions’. Consider the following example:

//the main function
 var myReturningFn1 = function(someVar){
      alert(someVar);
      //returning function
      return function(){
         alert(++someVar);
      };
   }
   
   var returnFn = myReturningFn1(111);
   returnFn();

In this function rather than returning a variable it returns a reference to the function. In other words if I were to do this:

myReturningFn1(111);

the output would be ‘111’.

But by doing:
var returnFn = myReturningFn1(111);
we are getting a reference to the return function. And to execute all we do
returnFn() and the output would be 112.

I could have written the function like so:

 var myReturningFn1 = function(someVar){
      alert(someVar);
      
      var returnFn = function(){
         alert(++someVar);
      }; 
      return returnFn; 
   }
   
   var returnFn = myReturningFn1(111);
   returnFn();

However you must realize that the first way of writing is more in vogue.

Getting back to the first way of writing the function an astute reader will have realized that after doing:

var returnFn = myReturningFn1(111);

The function myReturningFn1 has finished and gone out of scope and so has the variable someVar! But when you now do

returnFn() it actaully increments someVar. Which means that even if the outer function has gone out of scope the inner function still has access to its variables. This is called a ‘closure’, one of the most important concepts of a functional language and a very powerful feature of JavaScript. In this case the outer function myReturnFn1 closes over the inner function resulting in a closure.

More than that, one of the most valuable qualities of the returning functions is that you on the outside do not have any access to the variables of the outer function. Only the returning or the inner function does. You may say they are private variables:-)

One typical pattern I love to use in my programs is:

var myReturningFn1 = function(someVar){
      alert(someVar);
      var someObj = {
        init: function(){
         alert('Init! - ' + ++someVar);
        } 
      };
      return someObj;
   }
   
   var returnFn = myReturningFn1(111);
   returnFn.init();

The output in this case is ‘Init! – 112’

This way I have my methods neatly tucked away and my private variable safeguarded from accidental changes.

Finally my next favorite is the ‘immediate functions’. Consider the following:

 (function myImmediateFn(){
      alert('Executed!');
   })();

The output will be ‘Executed!’

The beauty of this is that the function is declared, executed and then destroyed, all in in go. If you wanted to pass in a parameter then we could write this as:

Finally my next favorite is the ‘immediate functions’. Consider the following:

 (function myImmediateFn(someVar){
      alert('Executed! - ' + someVar);
   })(88);

The output will be ‘Executed! – 88’

This pattern is also called the (function(){})(); pattern.

This is used very often in plugins.

(function($) {
  //your plugin code
})(jQuery);

I tend to use this pattern quite a bit when I want my libraries to be initialized on load.

I hope this essay has created an appetite for more functional exploration.

If you plan to go ahead I must recommend these three books by JavaScript gurus!

1. Secrets of the JavaScript Ninja – John Resig
2. JavaScript Patterns – Stoyan Stefanov
3. JavaScript: The Good Parts – Douglas Crockford

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s