Posts Tagged ‘webdev’

Simple JavaScript AOP framework

May 27, 2009

Here’s a simple JavaScript AOP framework for aspect oriented programming that I have been playing with:

/**
 * AOP framework for aspect oriented programming in JavaScript
 */

 var AOP = AOP || function() {

     //Private methods

     function toArray(iterable) {
         if (!iterable) return [];
         if (iterable.toArray) return iterable.toArray();
         var length = iterable.length || 0, results = new Array(length);
         while (length--) results[length] = iterable[length];
         return results;
     }

     //Public methods

     var public = {
         around: function(obj, fname, advice) {
             var oldFunc = obj[fname];
             obj[fname] = function() {
                 var args = [oldFunc].concat(toArray(arguments));
                 return advice.apply(this, args);
             };
         },

         before: function(obj, fname, advice) {
             var oldFunc = obj[fname];
             obj[fname] = function() {
                 var args = [oldFunc].concat(toArray(arguments));
                 advice.apply(this, args);
                 return oldFunc.apply(this, arguments);
             };
         },

         after: function(obj, fname, advice) {
             var oldFunc = obj[fname];
             obj[fname] = function() {
                 var args = [oldFunc].concat(toArray(arguments));
                 oldFunc.apply(this, arguments);
                 return advice.apply(this, args);
             };
         },

         callMethod: function(args) {
             var argsArray = toArray(args);
             return argsArray[0].apply(this, argsArray.slice(1));
         }
     };

     return public;
 }();

You can try it out with the following test code:

function logBeforeAndAfter() {
	console.log("before");
	AOP.callMethod(arguments);
	console.log("after");
}

function logAfter(f) {
	console.log("after ...");
	if(arguments[1] == "world") {
		console.log("its world");
	}
}

testObject = {
	hello: function(who) {
		console.log("hello " + who);
	}
}

AOP.around(testObject, "hello", logBeforeAndAfter);

//	AOP.before(testObject, "hello", function() {console.log("before");})

//	AOP.after(testObject, "hello", logAfter);

testObject.hello("world");

Maybe not so useful yet, but a nice exercise anyway.