14

編集:わかりました、私は次の解決策が有効であると信じています:

  1. jQueryAOPプラグインを使用します。基本的に、古い関数をフックと一緒に関数サンドイッチにラップし、古い関数名に再割り当てします。これにより、新しく追加されたフックごとに関数がネストされます。
    jQueryが使用できない場合は、ソースコードを略奪するだけで、プラグインにjQueryの依存関係がないように見え、ソースは単純で非常に小さいものです。

  2. すべてのフックとそのターゲットを説明するオブジェクトと、最初の変更されていない関数を格納するオブジェクトを用意します。新しいフックを追加すると、以前のラッピング関数を再ラップする代わりに、元の関数の周りでラッピングがやり直されます。
    入れ子関数をエスケープし、代わりに2つのオブジェクトを処理します。フックを頻繁に追加/削除し、順序が狂っている場合、これはフックの処理が容易になることも意味する可能性があります。

すでに完了しているので、最初のものを使用します。パフォーマンスについて心配する必要はありません。また、元の関数は影響を受けないため、フック方法を切り替えても、フックの追加をやり直すだけで済みます。これは、単純な検索と置換の操作である可能性があります。


やあ、

関数Aがフックのセット(関数Aの前後に実行される関数)を持つメカニズムを作成することは可能ですか?

理想的には、関数Aはフック機能を認識しないため、フックを呼び出すために関数Aのソースコードを変更する必要はありません。何かのようなもの:

A = function(){
    alert("I'm a naive function");
};
B = function(){
    alert("I'm having a piggyback ride on function A!"+
          "And the fool doesn't even know it!");
};
addHook(B, A)//add hook B to function A
A()
//getting alerts "I'm a naive function"/"I'm having a 
//piggyback ride on function A! And the fool doesn't even know it!"

私は数時間何かをハックしようとしてきましたが、今のところ運がありません。

4

7 に答える 7

13

きれいではないかもしれませんが、うまくいくようです...

<script>

function A(x) { alert(x); return x; }
function B() { alert(123); }

function addHook(functionB, functionA, parent)
{
    if (typeof parent == 'undefined')
        parent = window;

    for (var i in parent)
    {
        if (parent[i] === functionA)
        {
            parent[i] = function()
            {
                functionB();
                return functionA.apply(this, arguments)
            }

            break;
        }
    }
}

addHook(B, A);

A(2);

</script>
于 2009-04-25T20:17:53.230 に答える
10

jQuery の AOP プラグインを見てください。一般的には、「javascript アスペクト指向プログラミング」をググってください。

于 2009-04-25T20:13:44.083 に答える
4

非常に簡単な答え:

function someFunction() { alert("Bar!") }
var placeholder=someFunction;
someFunction=function() {
  alert("Foo?");
  placeholder();
}
于 2010-10-18T18:05:32.350 に答える
2

この答えは決定的なものではなく、これまでに提供されたものとは異なる手法を示しています。これは、Javascriptの関数がファーストクラスのオブジェクトであるという事実を利用しているため、a)別の関数に値として渡すことができ、b)プロパティを追加することができます。これらの特性を関数の組み込みの「呼び出し」(または「適用」)メソッドと組み合わせると、解決に向けたスタートを切ることができます。

var function_itself = function() {
    alert('in function itself');
}
function_itself.PRE_PROCESS = function() {
    alert('in pre_process');
}
function_itself.POST_PROCESS = function() {
    alert('in post_process');
}

var function_processor = function(func) {
    if (func.PRE_PROCESS) {
        func.PRE_PROCESS.call();
    }
    func.call();
    if (func.POST_PROCESS) {
        func.POST_PROCESS.call();
    }        
}
于 2009-04-25T21:05:30.357 に答える
1

次の関数は、スタックできる前後のフックを提供します。したがって、指定された関数の前または指定された関数の後に実行する必要がある潜在的な関数が多数ある場合、これは実用的なソリューションになります。このソリューションは jQuery を必要とせず、ネイティブの配列メソッドを使用します (shim は不要です)。また、コンテキストに依存する必要があるため、コンテキストを使用して元の関数を呼び出す場合は、関数の前後にそれぞれ同様に実行する必要があります。

// usage: 
/*
function test(x) {
    alert(x);
}

var htest = hookable(test);

htest.addHook("before", function (x) {
    alert("Before " + x);
})
htest.addHook("after", function (x) {
    alert("After " + x);
})

htest("test") // => Before test ... test ... After test
*/
function hookable(fn) {
    var ifn = fn,
        hooks = {
            before : [],
            after : []
        };

    function hookableFunction() {
        var args = [].slice.call(arguments, 0),
            i = 0,
            fn;
        for (i = 0; !!hooks.before[i]; i += 1) {
            fn = hooks.before[i];
            fn.apply(this, args);
        }
        ifn.apply(this, arguments);
        for (i = 0; !!hooks.after[i]; i++) {
            fn = hooks.after[i];
            fn.apply(this, args);
        }
    }

    hookableFunction.addHook = function (type, fn) {
        if (hooks[type] instanceof Array) {
            hooks[type].push(fn);
        } else {
            throw (function () {
                var e = new Error("Invalid hook type");
                e.expected = Object.keys(hooks);
                e.got = type;
                return e;
            }());
        }
    };

    return hookableFunction;
}
于 2011-09-27T05:26:29.837 に答える
0

これが役立つかどうかはわかりません。元の関数を変更する必要はありますが、一度だけであり、フックを起動するために編集し続ける必要はありません

https://github.com/rcorp/hooker

于 2015-01-01T17:14:33.717 に答える
0

これが私がやったことです。このような他のアプリケーションで役立つかもしれません:

//Setup a hooking object
a={
    hook:function(name,f){
        aion.hooks[name]=f;
    }
}a.hooks={
    //default hooks (also sets the object)
}; 

//Add a hook
a.hook('test',function(){
    alert('test');
});

//Apply each Hook (can be done with for)
$.each(a.hooks,function(index,f){
    f();
});
于 2013-04-23T20:52:33.563 に答える