3

2dcontextオブジェクトのいくつかのメソッドの機能を拡張しようとしていますが、希望どおりに機能させることができません。メソッドをオーバーライドしたいのですが、オーバーライドされたメソッドから元のメソッドを呼び出したいのです。これ:

//First get the original context
var ctx = canvas.getContext("2d");

//Create a class which uses ctx as it's prototype
var ExtendedContext = function (){};
ExtendedContext.prototype = ctx;

//And extend a method
ExtendedContext.prototype.fillRect = function(x, y, width, height) {
    //Do some stuff
    this.prototype.fillRect(x, y, width, height); //Doesn't work
    //Do some more stuff
};

fillRect自分のメソッド内から元のメソッドを呼び出すにはどうすればよいですか?

4

3 に答える 3

3

元の関数の参照を次のように保存できます。

var oldFillRect = ctx.fillRect;

そしてそれを次のように呼び出します

ExtendedContext.prototype.fillRect = function() {
    //Do some stuff
    oldFillRect.apply(this, arguments);
    //Do some more stuff
};

このテクニックは、「ダック パンチング」または「ファンクション フック」と呼ばれることもあります。Object.getPrototypeOfこの特定のインスタンスでは、メソッドを使用して元の関数参照を取得することもできます。これは次のようになります

ExtendedContext.prototype.fillRect = function() {
    //Do some stuff
    Object.getPrototypeOf(ExtendedContext.prototype).fillRect.apply(this, arguments);
    //Do some more stuff
};

したがって、参照を保存する必要さえありません。

于 2012-05-03T11:14:18.073 に答える
1

古い名前を別のオブジェクトに保存する必要はありません。クロージャを使用してください:

ExtendedContext.prototype.fillRect = (function () {
  var oldf = ExtendedContext.prototype.fillRect;
  return function () {
    //Do some stuff
    oldf.apply (this, arguments);
    //Do some more stuff
  };
}) ();

これを行うことがたくさんある場合は、次のことが役立ちます。

function extend (fnc) {
  var mthd = (fnc.toString ().match (/^function\s+(\w+)\s*\(/) || ['', ''])[1];

  if (mthd in ExtendedContext.prototype)
    throw ('ExtendContext method ' + mthd + 'does not exist');  

  ExtendedContext.prototype['_' + mthd] = ExtendedContext.prototype[mthd];
  ExtendedContext.prototype[mthd] = fnc;
}

次に、次のようにextendを呼び出すことができます

extend (function fillrect () {    
  // Do some stuff
  this._fillrect.apply (this, arguments);
  // Do some more stuff
});

古いメソッドを参照するには、「_」で始まる名前を使用します

于 2012-05-03T12:26:21.433 に答える
0

私は数か月遅れていますが、この機能を実現するためにかなりシンプルなデザインを使用しています。JavaScriptの構造はグローバルオブジェクトから実行され、コードをグローバル変数から保護します。

ページ/ユーザーコントロールごとに、新しいオブジェクトを保持するようにグローバルオブジェクトを変更していますが、一部のコードでは、場所ごとに異なる機能が必要であり、拡張メソッドが必要です。コードを複製して拡張インスタンスのオブジェクト全体を再定義したり、コードがどのように拡張されているかを気にしたりする必要はありません。

アヒルが思い通りになるまでパンチする代わりに、ジェネリック拡張メソッドを作成してみませんか?私たちのケースを使用して、ここに例があります:

// Using a Global JavaScript object:
GlobalNameSpace.ExtensionFunction = function(oParam1, oParam2, oParam3)
{
   /// <summary>All parameters are optional</summary>

   return; // For instances when it is not being overwritten, simply return
}

//In the Code to be extended:
GlobalNameSpace.Control.ControlFunction(oSender, oArgs)
{
    ///<summary>Control's function</summary>

    // Function-y stuff..
    GlobalNameSpace.ExtensionFunction(oSender, oArgs);
}

//and finally in the code to extend the functionality
GlobalNameSpace.Page.Init
{
    ///<summary>Initializes the page</summary>

    // redefine the extension function:
    GlobalNameSpace.ExtensionFunction = function(oSender, oArgs)
    {
        // Call the extension function, or just code the extension here
        GlobalNameSpace.Page.Function(oSender, oArgs); 
    }
}

このメソッドの欠点は、一度に複数のオブジェクトに対してこれを実行する場合です。その時点で、拡張メソッドを、特に拡張したいコードに移動することをお勧めします。これを行うと、その拡張コードの一般性が低下しますが、必要に応じて決定できます。

于 2012-10-25T15:45:55.053 に答える