DEV Community

George Jempty
George Jempty

Posted on

Quick and Dirty Aspect Oriented (AOP) Javascript with a Couple Dozen Lines of Code

Aspect oriented programming (AOP): everybody's talking about and nobody's doing it. Actually, nobody's even talking about it, because they would be if there were sufficient use cases; we will return to that at the end.

A year or two ago though I needed to somehow augment a callback function in Javascript, and when I found the following Stackoverflow answer I was immediately reminded of AOP. The code follows:

var original = callback; //existing function
callback = function() {
    // Do something with arguments:
    console.log(arguments);
    return original.apply(this, arguments);
};

In AOP the original function still executes as it normally would, it's just that it gets augmented with other behavior. I refer you to the wikipedia article for a more formal definition, but will specifically rely on the following use case it mentions: "log all function calls when the function's name begins with 'set'".

I've implemented this at the following repl; you can go there and click "Run" to see it in action. The code also follows:

const myModule = (function() {
  let result;
  const my = {
    setResult(x,y) {
      result = x + y;
    },
    getResult() {
      return result;
    }
  }
  return my;
})();

const predecessor = function() {
  console.log('arguments: ', arguments);
}

let precedableFns = {};

for (let fname in myModule) {
  if (/^set[A-Z]/.test(fname)) {
    precedableFns[fname] = myModule[fname]; //save original function
    myModule[fname] = function() {
      predecessor.apply(this, arguments);
      precedableFns[fname].apply(this, arguments); //run original
    }
  }
}

myModule.setResult(2,3);
console.log(myModule.getResult());

myModule.setResult(3,4);
console.log(myModule.getResult());

There are a lot of possibilities beginning from the above. For one, you might have a "successorFn" that gets executed from a setTimeout immediately before/after (before lexically, after functionally) a function returns.

And a more interesting use case might be to only perform console logging when the server host is localhost or some other value you are interested in. The possibilities are endless, if somewhat arcane.

Top comments (0)