Extending an Ajax Component 
August 14th, 2006
Ajax components are not only cool but actually quite useful - and I am not just saying that as a component vendor but as a web application developer. At nitobi we do both consulting and component development and when doing consulting we shy away from actually changing the component source code to do things that we need and instead focus on extending core components.
Since JavaScript is a dynamic language, one can really easily extend functionality. Most notably, many will have at least heard of aspect oriented programming which is the idea of adding before, after, or around advice - which just means running some code before, after or around some predefined method.
Let’s take a look at a quick example. As many already know, classes in JavaScript are defined as functions.
// Define the Dog class
function Dog()
{
this.breed = ‘berner’;
}
// Define the speak method on the Dog class
Dog.prototype.speak = function()
{
alert(’w00f’);
}
That defines a Dog class that has a public property for the dog breed and a public method to make that pooch sing.
So let’s pretend that I am an Ajax component vendor (who knew) and to make my JavaScript load faster I might go ahead and remove the white-space, remove comments, and even replace long variable names with shorter ones. This all happens when I “compile” my JavaScript on my server before I let people access it.
If this were a compiled DLL say, then it would be more problematic to do something like change what the dog says based on the breed of the dog - particularly if this has to be done at runtime rather than compile time. Luckily for us AJAX developers, JavaScript is very flexible
The first thing that we can do is create a new instance of our Dog class and actually replace the speak method with something completely different.
// Create a new instance of a Dog
var berner = new Dog();
// Re-define the speak method for this instance only
berner.speak = function() {
alert(’I am a Bernese Mountain Dog’);
}
If we wanted to change every new instance of the Dog class we can also change the actual class definition by changing the prototype property just as the original author did.
// Re-define the speak method for the class
Dog.prototype.speak = function()
{
alert(’I am a ‘ + this.breed);
}
Alternatively, we can also add code that will run before or after the speak function. We can define a static function called attachAfter in the aspect namespace that will take an object to which some method belongs (sourceContext), a string that is the name of a method on that object (sourceMethod), and a reference to function object that we want to call after the source method is called (aspectMethod). aspect.attachAfter is pretty simple and looks something like this:
aspect.attachAfter = function(sourceContext, sourceMethod, aspectMethod)
{
var oldMethod = sourceContext[sourceMethod];
sourceContext[sourceMethod] = function()
{
oldMethod.apply(sourceContext, arguments);
aspectMethod.apply(sourceContext, arguments);
}
}
We use the JavaScript apply method here such that we can pass the arguments list that the method is to be called with. To actually use this with our Dog class we could either augment the instance of the class or even the class itself. Here is an example of attaching some function that will alert the breed property of the dog after the dog speaks.
var berner = new Dog();
// This will just alert ‘w00f’ as we expect
berner.speak();
// Now attach an after function to the speak method
aspect.attachAfter(berner, “speak”, function(){alert(’I am a ‘+this.breed)});
// This will now alert ‘w00f’ and then ‘berner’
berner.speak();
Notice that we can even execute the after function in the context of the berner object and therefore we have access to the this keyword in our attached function.
I am going to look at more JavaScript features in the coming weeks including inheritance and dynamic XML parsing. If anyone sees any problems here let me know!
Technorati Tags: ajax, components, javascript, patterns, architecture
Del.icio.us
This entry was posted on Monday, August 14th, 2006 at 11:38 pm and is filed under AJAX, JavaScript, Architecture, Components. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

August 15th, 2006 at 10:36 am
Hey Dave - Just wondering how we would go about generalizing this attachAfter so that we could do it to the
Dogclass rather than an instance of it?And even further, many aspect oriented frameworks use rules to decide when and how to attach functions. Any thoughts on doing this in Javascript? I was thinking of something like:
aspect.registerBefore({prefix: 'write'}, function() { document.write('\n'); });Where this would write a newline before executing any function that began with ‘write’. Other rules could be ‘contains’ or ‘class_is’ or stuff like that.
August 15th, 2006 at 10:48 am
interesting piece. i heard your podcast that touched on this and have been looking forward to the post. if possible, maybe you can touch on the differences, pros/con of defining classes with properties and methods without using the prototype keyword:
someClass = function()
{
this.someProperty = 13;
someMethod = function()
{
alert(’i am someMethod’);
}
}
August 15th, 2006 at 2:18 pm
heya jake, you could simply call aspect.attachAfter with sourceContext as Dog.prototype and the resulting aspects would be attached to your class so all the instances would get that code.
It would be pretty easy to attach to methods based on some search criteria as well. Since we use the string name of the class we can parse that using a regex or whatever.
August 15th, 2006 at 2:32 pm
hey mamund,
I have got a fairly long article about that topic almost ready to go.
There is some performance difference but the biggest difference is if you want to support things like protected variables. Protected / private variables depend on closures and so cannot be achieved with class.prototype syntax.
There are some other considerations such as doing inheritance - ie you can’t really inherity members that are defined as inner functions or properties - and also documentation. We use JSDoc which works well on class.prototype syntax code.
I will go further into the details soon!