Search code examples
javascriptaspect

Something Aspected-Oriented in Javascript


So, i made this code to help me add functions after or before other functions, but i couldn't figure out a better way to do that, i had to use eval() and that is really not a good practice. At first, i tried to do something like:

Function.prototype.append = function(fn){
    eval("this = function(){ ("+this.toString()+").apply(this, arguments); fn.apply(this, arguments); }");
}

hello = function(){
    console.log("hello world!");
}

hello(); // hello world!
hello.append(function(){
    console.log("bye world!");
});
hello(); // hello world! bye world

but it didn't work since the function can't change itself. So i did this:

Aspects = new Object();

Aspects.append = function(aspect, fn){
    eval(aspect + " = function(){ ("+eval(aspect + '.toString()')+").apply(this, arguments); fn.apply(this, arguments); }");
}

Aspects.prepend = function(aspect, fn){
    eval(aspect + " = function(){ fn.apply(this, arguments); ("+eval(aspect + '.toString()')+").apply(this, arguments); }");
}

hello = function(){
    console.log("hello world!");
}

hello(); // hello world!

Aspects.append('hello', function(){
    console.log("bye world!");
});

hello(); // hello world! bye world!

i don't want to work with objects or anything, i just want to add more code after or before my already declared function


Solution

  • I have a utility library called fcombine which supports

    f1 = fcombine.pre(new_function, f1);
    f1 = fcombine.post(f1, new_function);
    

    The reason your code is ugly is because your not returning the new function.

    The problem with your code is also that it uses eval and tries to do too much magic. The whole idea of passing in a string of a variable name then evalling that is absolutely horrible.

    You can quite easily write

    hello = Aspects.append(hello, new_function);

    As demonstrated by fcombine.post