我正在尝试扩展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
方法?
答案 0 :(得分: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
};
所以你甚至不需要存储引用。
答案 1 :(得分: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
});
要引用旧方法,请使用前缀为“_”
的名称答案 2 :(得分:0)
我迟到了几个月,但我使用了一个相当简单的设计来实现这个功能。我们的JavaScript结构运行一个全局对象,以保护我们的代码免受全局变量的攻击。</ p>
对于每个页面/ usercontrol,我们正在修改我们的全局对象以保存新对象,但是某些代码在不同的地方需要不同的功能,需要扩展方法。我们不想复制代码并重新定义扩展实例的整个对象,我们不希望代码关心如何扩展它。
为什么不创建一个通用的扩展方法,而不是在它完成你想要的东西之前打孔。使用我们的案例,这是一个例子:
// 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);
}
}
此方法的缺点是,如果您希望一次为多个对象执行此操作,此时将扩展方法移动到您特别想要扩展的代码中可能更好。这样做会使扩展代码不那么通用,但可以根据您的需要来决定。