164

a()オーバーライドしたい関数がありますa()が、コンテキストに応じた順序で元の関数を実行することもできます。たとえば、ページを生成するときに、次のようにオーバーライドしたい場合があります。

function a() {
    new_code();
    original_a();
}

そして時々このように:

function a() {
    original_a();
    other_new_code();
}

original_a()オーバーライド内からそれを取得するにはどうすればよいa()ですか?それも可能ですか?

このようにオーバーライドする代わりの方法を提案しないでください。私は多くのことを知っています。具体的にはこの方法について質問しています。

4

12 に答える 12

180

次のようなことができます。

var a = (function() {
    var original_a = a;

    if (condition) {
        return function() {
            new_code();
            original_a();
        }
    } else {
        return function() {
            original_a();
            other_new_code();
        }
    }
})();

匿名関数内で宣言original_aすると、グローバル名前空間が乱雑になるのを防ぐことができますが、内部関数で使用できます。

コメントで言及されている Nerdmaster のように、必ず()最後に を含めてください。外側の関数自体を に格納するのではなく、外側の関数を呼び出して結果(2 つの内側の関数の 1 つ) をに格納します。aa

于 2008-11-17T20:01:58.303 に答える
91

Proxy パターンは次のことに役立ちます。

(function() {
    // log all calls to setArray
    var proxied = jQuery.fn.setArray;
    jQuery.fn.setArray = function() {
        console.log( this, arguments );
        return proxied.apply( this, arguments );
    };
})();

上記は、そのコードを関数でラップして、「プロキシされた」変数を非表示にします。jQuery の setArray メソッドをクロージャに保存して上書きします。次に、プロキシはメソッドへのすべての呼び出しをログに記録し、呼び出しを元のメソッドに委任します。apply(this, arguments) を使用すると、呼び出し元が元のメソッドとプロキシされたメソッドの違いに気付かないことが保証されます。

于 2008-11-17T20:03:56.193 に答える
28

皆さん、プロキシパターンが本当に役に立ちました.....実際、私はグローバル関数fooを呼び出したかったのです。特定のページでは、いくつかのチェックを行う必要があります。だから私は次のことをしました。

//Saving the original func
var org_foo = window.foo;

//Assigning proxy fucnc
window.foo = function(args){
    //Performing checks
    if(checkCondition(args)){
        //Calling original funcs
        org_foo(args);
    }
};

Thnxこれは本当に私を助けました

于 2009-11-16T06:56:02.427 に答える
11

You can override a function using a construct like:

function override(f, g) {
    return function() {
        return g(f);
    };
}

For example:

 a = override(a, function(original_a) {
      if (condition) { new_code(); original_a(); }
      else { original_a(); other_new_code(); }
 });

Edit: Fixed a typo.

于 2010-01-31T05:33:55.617 に答える
4

任意の引数を渡す:

a = override(a, function(original_a) {
    if (condition) { new_code(); original_a.apply(this, arguments) ; }
    else { original_a.apply(this, arguments); other_new_code(); }
});
于 2012-01-31T17:24:27.047 に答える
3

@Matthew Crumley が提供する答えは、すぐに呼び出される関数式を利用して、返された関数の実行コンテキストに古い「a」関数を閉じることです。これが最良の答えだったと思いますが、個人的には、IIFE の引数として関数 'a' を渡すことを好みます。よりわかりやすいと思います。

   var a = (function(original_a) {
        if (condition) {
            return function() {
                new_code();
                original_a();
            }
        } else {
            return function() {
                original_a();
                other_new_code();
            }
        }
    })(a);
于 2016-11-17T12:49:40.640 に答える
2

上記の例は、関数オーバーライドに正しく適用thisまたは渡されません。argumentsアンダースコア_.wrap()は、既存の関数をラップし、正しく適用thisして渡します。arguments参照: http: //underscorejs.org/#wrap

于 2012-09-19T02:00:24.980 に答える
0

複数のライブラリの関数をオーバーライドする必要が頻繁にあったため、同様のシナリオ用に小さなヘルパーを作成しました。このヘルパーは、"名前空間" (関数コンテナー)、関数名、およびオーバーライド関数を受け入れます。参照された名前空間の元の関数を新しい関数に置き換えます。

新しい関数は元の関数を最初の引数として受け入れ、元の関数の引数を残りとして受け入れます。コンテキストは常に保持されます。void 関数と非 void 関数もサポートしています。

function overrideFunction(namespace, baseFuncName, func) {
    var originalFn = namespace[baseFuncName];
    namespace[baseFuncName] = function () {
        return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
    };
}

たとえば Bootstrap での使用法:

overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
    // ... do stuff before base call
    baseFn(obj);
    // ... do stuff after base call
});

ただし、パフォーマンス テストは作成しませんでした。シナリオによっては、不要なオーバーヘッドが追加される可能性があります。

于 2015-11-25T09:19:18.883 に答える
0

すべての状況で機能するかどうかはわかりませんが、私たちの場合、describeJest で関数をオーバーライドして、名前を解析し、describeいくつかの基準を満たした場合にブロック全体をスキップできるようにしました。

これが私たちのために働いたものです:

function describe( name, callback ) {
  if ( name.includes( "skip" ) )
    return this.describe.skip( name, callback );
  else
    return this.describe( name, callback );
}

ここで重要なことは次の 2 つです。

  1. アロー関数は使用しません() =>

    アロー関数は参照を に変更し、thisそれがファイルのthis.

  2. andの代わりにthis.describeandを使用します。this.describe.skipdescribedescribe.skip

繰り返しますが、それが誰にとっても価値があるかどうかはわかりませんが、もともとMatthew Crumley の 優れた答えを回避しようとしましたが、メソッドを関数にし、条件でそれらを解析するためにパラメーターを受け入れる必要がありました。

于 2020-06-05T21:54:23.290 に答える