Pregunta

I want to do an AOP-like 'before' functionality for JavaScript functions.

So I looked for existing solution and found the aop-plugin for jQuery. Unfortunately the plugin simply wraps the given function. So any object that points to the original function before enhancing the function, still points to the original function. Calling the function from these objects calls the not enhanced version of the function.

Instead of wrapping functions with other functions, I want to change the function object itself, so previous references do not cause unanticipated behaviour. So I got something like this:

(function(){}).constructor.prototype.before = function(beforeFunction){
    this.beforeFunction = beforeFunction;
};

/* some magic should happen here: enhance call? */

function logFoo() {
    console.log("Foo");
};
function logBar() {
    console.log("Bar");
};

logFoo(); // logs "Foo"

logFoo.before(logBar);

logFoo(); // should log "Bar", then "Foo"

So the question is, how do I get the beforeFunction invoked, when the enhanced function is called?

¿Fue útil?

Solución

The body, parameters and referencing environment of a function are immutable so you cannot enhance a function, you can only make new functions.

You could make your function enhanceable from the beginning like this:

Function.prototype.enhanceable = function() {
    var original = this,
        enhanced = [],
        ret = function() {
            for( var i = 0; i < enhanced.length; ++i ) {
                enhanced[i].apply( this, arguments );
            }

            return original.apply( this, arguments );
        };

    ret.before = function( fn ) {
        enhanced.push( fn );
    };

    return ret;
};

Then:

var logFoo = function() {
     console.log( "foo" );
}.enhanceable();

var logBar = function() {
     console.log( "bar" );
};

logFoo(); //foo

logFoo.before( logBar );

logFoo(); //logs bar, then foo
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top