Anonymous Classes in JavaScript and the XMLHttpRequest API

A conversation I had today reminded me of a JavaScript design pattern I’ve seen in use, but I’ve never seen described… anonymous classes. Anonymous classes are not explicity supported by JavaScript 1.5, but this technique is basically possible, and I’ve seen them used in cases where they greatly enhanced readability, and appeared to be a really natural way of solving a problem.

While in Java, they are a language feature, in JavaScript, techniques for anonymous classes strike me as more of a design pattern than something offered directly by the language.

This is not an original concept… specifically, I’ve seen anonymous classes used in JavaScript in the source code for Sarissa and in some Mozilla code somewhere (maybe the JavaScript SOAP client or XML-RPC client).

The idea for using anonymous classes in JavaScript almost surely comes from their use in Java:


ActionListener listener = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        doStuffInOtherThread();
        updateGuiWithResult();
    }
};

Without going into great detail, you can see that in the sample above, a class is defined, an instance is instantiated, and the class is discarded all in one go. Although this might seem strange if you’re not familiar with them, anonymous classes can actually be a highly elegant way of solving certain problems when a ‘one-off’ class is needed… often used for Iterators (like generators in Python) or to substitute small objects for C/Python method pointers.

On top of all that, ActionListener in the code above is not even a class… it’s an interface, which cannont normally be directly instantiated. More coolness! So in the sample above, you actually define an implementation of an interface without giving it a name so that it can never be referenced again. Anyway… whatever… let’s talk about applying this pattern to JavaScript.

It’s not uncommon to pass references to function objects around in JavaScript… just to name a popular example, in DOM Level 2 Events Module code, you often see:


function myCallback() {
    ...
}

nodeRef.addEventListener('click',myCallback,false);

Another popular example… in Ajax libraries, you often see assignment of a function reference to an XMLHttpRequest instance’s onreadystatechange instance method:


function myCallback() {
    ...
}

var client = new XMLHttpRequest();
client.onreadystatechange = myCallback;

While the XMLHttpRequest class is certainly a major step forward for JavaScript in the browser, you have to admit… this API is crap (for many reasons beyond what is discussed here). Looks like the guys at Microsoft came up with this one afternoon as a quick solution, implemented it, and never bothered to go back and refactor before shipping the first version of IE to use it (IE 5.0?). You’d expect better API design from Microsoft developers.

The low quality of the API is evidenced by the sheer number of Ajax libraries that are now popping up that claim to ‘wrap’ XMLHttpRequest into an easier interface. Hopefully, we can decide on a standard, and hopefully it will include the concept of anonymous classes… instead of passing a function reference to a JavaScript function, why not pass a reference to a JavaScript object that implements an known interface? Which, in JavaScript terms, means implements a method with a specific signature or name.


var listener = {
    id: 123,

    responseReceived: function (evt) {
        // implement callback here
        ....
    },

    otherHelperMethod: function() {
        ....
    }
};
var client = new BetterHttpClientAPI();
client.addListener(listener);

Or, you could get really terse, and do this:


var client = new BetterHttpClientAPI();
client.addListener({
    id: 123,

    responseReceived: function (evt) {
        ....
    },

    otherHelperMethod: function() {
        ....
    }
});

Notice how these examples allow you to package instance properties (fields, variables, attributes, whatever) and instance methods along with the actual callback method to be called when the HTTP response is received (responseReceived becomes the callback method here). JavaScript has many object-oriented features… why not use them???? Sure… you don’t need this kind of functionality… you can always just define a bunch of global functions and global variables to be used by your callback function, but, then you lose all the benefits that OO offers with regard to combining state and behavior into a single, encapsulated entity!

This approach is highly related to the Delegation Event pattern often seen in Java (JavaBeans, Swing, etc…), and offers a natural way to add multiple listeners for events, and loosen dependencies.

Let’s take JavaScript to the next level and start using these ideas!

Does anyone have any examples of this pattern currently in use in JavaScript? Do any of the various new breed of Ajax toolkits/APIs use anonymous classes or Delegation Event?

The JavaScript DOM 2 Events Module bindings have shunned the idea of object references in favor of function references… by why should that hold us back when developing new APIs?


About this entry