May 28 2010

Create a jQuery like chainable JavaScript toolbox specific to your project

Category: NovoGeek @ 06:44

"Global variables are evil" is what the JavaScript Guru Douglas Crockford says, as they are the source of unreliability and insecurity. How elegant your code would be if you wrap your entire project's code under a single global namespace?

[Did you know? The entire JavaScript code of Yahoo's website is accessible through a single global 'YAHOO' object!]

In this article, I would like to show how you can create a chainable JavaScript library(not a library exactly, but sort of a toolbox) specific to your project. The concept is nothing new., this is how libraries like jQuery are built. It is more about understanding certain design patterns in JavaScript.

The first thing to know is:

(function(){ 
    //your code here....
})(); 

This is nothing but a self executing anonymous function. All it does is, it simply executes whatever code you write inside it and disappears after that. The private variables declared inside this function are not exposed to the global scope, unless specifically attached to the window object.

The next thing to know is about Prototypal Inheritance in JavaScript. This is a huge topic in itself and the article assumes that the reader is familiar with this concept. The idea is, in our anonymous function, we would have a private function and prototype it with our custom functions.

This is how our JavaScript toolbox looks like: 

(function(){
    var mySpace=function(){
        return new PrivateSpace();
    }
 
    var PrivateSpace=function(){
    };    
 
    PrivateSpace.prototype={
        init:function(){
            console.log('init this:', this);
            return this;
        },
        ajax:function(){
            console.log('make ajax calls here');
            return this;
        },
        cache:function(){
            console.log('cache selectors here');
            return this;
        }
    }
    window.my$=mySpace();
})();

In the above code, "PrivateSpace" is a private function which is prototyped with our desired functions. "mySpace" is a function which returns a new instance of "PrivateSpace" when executed.

As said before, our anonymous function executes once and does not expose these functions to the outer world. To expose our functions under a namespace, we should add the instance of our "PrivateSpace" to a window level(global) object. This is exactly what the last line of the code does.

So, when we say

window.my$=mySpace(); 

we are executing "mySpace()", which returns a new instance of  "PrivateSpace()" function and assigning it to "my$", which is a window level object. So if you print my$ like:

console.log(my$);

, you would get all the functions present in the "PrivateSpace()" prototype. So you can call your functions like: my$.ajax(), my$.cache() etc.

Note that each function in "PrivateSpace()" returns "this". i.e., each function returns an instance of "PrivateSpace()" and hence you can chain your methods like:

my$.init().ajax();

That's it! Now we have our own JavaScript toolbox specific to our project! So no more global functions in our projects. As said, this is nothing new to the JavaScript world,  this pattern is what jQuery uses for chaining the methods.

I have faced few problems while opting for this pattern and posted them in StackOverflow. Folks there are kind to answer and hence this article. I'm no JS guru to say this is 100% perfect, but I have implemented this without any issues in a huge project.  You may refer Chapter 6 (Chaining) in  Pro JavaScript Design Patterns which explains about this jQuery like pattern.

Do you have better ideas? Please let me know.

Happy coding :)

Tags: ,

blog comments powered by Disqus