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 回答