如何在纯 JavaScript 中覆盖原生 JS 函数(canvas 的 drawImage())?

Max*_*e E 3 html javascript overriding function

我需要在每次调用画布 2D 上下文上完成的函数 drawImage() 时执行一些代码。

game.canvas = document.getElementById('canvas');
game.ctx = game.canvas.getContext("2d");
Run Code Online (Sandbox Code Playgroud)

不幸的是,这并不像看起来那么容易。

我试图这样做:

game.ctx.drawImageOld = game.ctx.drawImage;
game.ctx.drawImage = function(i,x,y,u,v){console.log("ok"); game.ctx.drawImageOld(i,x,y,u,v);}
game.ctx.drawImage(myImage, 10, 10);
// logs "ok" two times on FF
Run Code Online (Sandbox Code Playgroud)

和这个

CanvasRenderingContext2D.prototype.drawImageOld = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function(i,x,y,u,v){console.log("ok"); this.drawImageOld(i,x,y,u,v);}
game.ctx.drawImage(myImage, 10, 10);
// logs "ok" two times
Run Code Online (Sandbox Code Playgroud)

但是本机 drawImage 永远不会执行......

我该怎么做?还有另一种“检测”函数调用的方法吗?

谢谢。

Fel*_*ing 5

你打电话时

CanvasRenderingContext2D.prototype.drawImageOld(i,x,y,u,v);
Run Code Online (Sandbox Code Playgroud)

然后在里面drawImageOld,this将引用CanvasRenderingContext2D.prototype,而不是实际的 Context2D 实例。这基本上就是错误告诉你的。

您可以使用.call [MDN].apply [MDN]显式传递实例:

(function() {
    var orig_drawImage = CanvasRenderingContext2D.prototype.drawImage;

    CanvasRenderingContext2D.prototype.drawImage = function() {
        console.log("ok");
        orig_drawImage.apply(this, arguments);
    };
}());
Run Code Online (Sandbox Code Playgroud)

话虽如此,但不能保证这将适用于所有浏览器。宿主对象,即 ECMAScript 规范未涵盖的对象,并不总是必须遵循所有规则。一些浏览器也可能定义 drawImage为只读。