2

我想为 JavaScript 函数做一个类似 AOP 的“之前”功能。

所以我寻找现有的解决方案并找到了 jQuery 的 aop-plugin。不幸的是,插件只是简单地包装了给定的函数。因此,任何在增强功能之前指向原始功能的对象,仍然指向原始功能。从这些对象调用函数会调用该函数的非增强版本。

我不想用其他函数包装函数,而是想更改函数对象本身,因此以前的引用不会导致意外行为。所以我得到了这样的东西:

(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"

所以问题是,当调用增强函数时,如何调用 beforeFunction?

4

1 回答 1

6

函数的主体、参数和引用环境是不可变的,因此您无法增强函数,只能创建新函数。

您可以像这样从一开始就使您的功能可增强:

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;
};

然后:

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

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

logFoo(); //foo

logFoo.before( logBar );

logFoo(); //logs bar, then foo
于 2012-11-20T11:30:43.673 回答