2012-05-03 35 views
3

我试图延长的2dcontext对象的某些方法的功能的,但我不能得到它的工作方式我想:我要重写的方法,但我想从调用重写的方法原始方法是这样的:JS扩展功能的方法

//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方法?

回答

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 
}; 

所以你甚至不需要存储参考。

+0

我忘了提及,但还有更多的方法需要覆盖,所以如果可能的话我不想保存手动覆盖的每个函数。但我想我可以简单地遍历所有函数,并将它们全部复制到某个对象。编辑:这个伎俩!谢谢! – Tiddo

+0

@Tiddo:看到更新。 'Object.getPrototypeOf'应该为你做。 – jAndy

+0

那是再好不过了!非常感谢! – Tiddo

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 (function fillrect() {  
    // Do some stuff 
    this._fillrect.apply (this, arguments); 
    // Do some more stuff 
}); 

要引用的旧方法使用其名称前缀“_”

+0

这也是一个非常好的解决方案! – Tiddo

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); 
    } 
} 

这种方法的短而来的是,如果你想在同一时间多个对象做到这一点,此时它可能是一个更好的主意来移动扩展方法放入您特别想要扩展的代码中。这样做会使扩展代码不那么通用,但可以根据您的需求来决定。