9 June 2008

My JavaScript patterns

Since posting about my JavaScript "rules", I have had a number of requests to expand on the patterns I use for developing my JavaScript objects.

I use two main patterns, a singleton pattern and a constructor pattern. A singleton is an object which will have only one instance within an application. A constructor is a function which when invoked with the new keyword will create an object based on its definition. These objects are known as instances.

Constructor Pattern
A constructor pattern is something which JavaScript has native support for. Douglas Crockford has previously talked about this pattern at length.

function EventHandler() {

    //constructor

 

    //private members

    var registeredEvents = [];

 

    //public methods

    this.registerHandler = function(func) {

        if (typeof func === "function") {

            registeredEvents.push(func);

        }

    }

    this.fire = function() {

        for (var i = registeredEvents.length-1; i >= 0; i--) {

            registeredEvents[i]();

        }

    }

}



A constructor is simply a function which defines various members and contains its own variables and indeed other functions. You can also define constructor logic with a series of statements which do not declare methods or private variables or functions.

Its a fairly simple pattern and it is just as easy to use. To declare a new instance of this constructor, the code is simply this:

var myEventHandler = new eventHandler();



Singleton Pattern
My aim with a singleton is to have a highly readable object formation pattern which allows for private members and the exposure of a public interface. The syntax also must ensure that only one instance of the singleton can exist though of course there is nothing to stop the object being inherited from.

I also wanted the pattern to look similar to the constructor pattern above. This should make it easier to code and maintain.

For this example, I am using a simplified version of an object in JSquared. JSquared makes extensive use of this pattern as much of the library is built up from singleton objects. The object I am using here is the cookies object. For details on how to use this within an application of your own, look out for a post on the JSquared blog.

var cookies = new (function() {

    //private members

    var cookies = {};

 

    //constructor

    //get the current set of cookies

    var currentCookies = document.cookie.split(";");

    var cookie;

    //loop through current cookies and add their values to the cookies collection

    for (var i = currentCookies.length - 1; i >= 0; i--) {

        cookie = currentCookies[i].split("=");

        if (cookie.length >= 2) {

            cookies[cookie[0]] = cookie[1];

        }

    }

 

    //public methods

    this.set = function(name, value, expiration) {

        document.cookie = name + "=" + value + ";expires=" + expiration + ";path=/";

        cookies[name] = value;

    }

    this.get = function(name) {

        return cookies[name];

    }

    this.delete = function(name) {

        this.set(name, "", -1);

        delete cookies[name];

    }

});



You will I am sure notice how similar this singleton pattern is to the constructor pattern above. The major difference is that the singleton pattern created the constructor as an anonymous function and then invoked an instance of that anonymous function immediately.

Just like when creating a new instance of a constructor, an object defined as per the constructor function will automatically be returned from the invocation. So in the example above, the variable cookies will contain the singleton.

The syntax may look odd, but it has proven itself very resilient and extremely effective. It allows for private members and functions, the public methods have access to those private members. It contains constructor logic and of course parameters can be passed in to the constructor just like they could be in the constructor pattern shown above.

As I seem to often say, its as simple as that!

6 comments:

Adam Silver said...

Very very useful, I have started to use both of these patterns and have found them to be very effective so far.

It is so simple yet powerful.

Anonymous said...

Very nice. I'm learning javascript and I've found that javascript functions are extremely powerful. I've blogged about it myself. Also how did you highlight the syntax? Thanks.

kouphax said...

Both very good patterns. Personally though I prefer the other singleton pattern

var myObj = function(){
// private area

// public return object
return {
init:function(){
}
}
}

Feels much cleaner to me but that's just a personal opinion

Adam Silver said...

Hi James, I have been looking all over the internet as to why there are brackets around the singleton anonomous constructor function. :(

alxdark said...

What do you think about the performance of recreating these methods on every object instance, rather than one time on their prototype? This is mainly why I have avoided the constructor function pattern you describe, despite its advantages.

James Norton said...

I don't really comment on using the prototype in this example of a constructor. I definitely think the prototype should be used whenever it is sensible to do so as there is a performance gain. However, if few instances created and used and there are few functions on the object, then it becomes less of a concern. As in all things, use the correct tool at the correct time!