4

我正在尝试向画布上下文中调用的每个方法添加一些代码。我正在尝试这样做,以便可以将每个命令添加到命令数组中。这是我认为有效的代码(但没有):

var canvas = Object.getPrototypeOf(document.createElement('canvas').getContext('2d'));
for(p in canvas){
    if(canvas.hasOwnProperty(p)){
        var original = canvas[p];
        canvas[p] = function(){

            //extra code to be run

            return original.apply(this,arguments);
        }
    }
}

在我看来,这似乎应该有效,但事实并非如此。如果我在示例中使用此代码,我会得到一个NOT_SUPPORTED_ERR: DOM Exception 9

演示:http: //jsfiddle.net/J3tUD/2/

4

2 回答 2

5

您遇到的问题是变量不是块作用域。

当您的函数运行时,它会更新上下文原型,以便每个函数调用相同的函数original,这是原始原型拥有的最后一个元素。在这种情况下,即webkitGetImageDataHD

这意味着当你打电话时ctx.beginPath();你真的打电话ctx.webkitGetImageDataHD();。这个方法需要 4 个参数,因为它没有得到它们,所以它会抛出 DOM 异常 9。

由于 JavaScript 不支持块作用域,因此您必须使用函数强制更改作用域。修改您的示例,我们可以创建一个新函数,其中original是一个固定值:

var context = Object.getPrototypeOf(document.createElement('canvas').getContext('2d'));

function bind(context, p) {
    // context, p, and original never change.
    var original = context[p];
    context[p] = function(){
        console.log(p, arguments);
        return original.apply(this,arguments);
    }
}

// p changes with every iteration.
for(p in context){
    if(context.hasOwnProperty(p)){
        bind(context, p);
    }
}

在这里找到一个工作演示:http: //jsfiddle.net/bnickel/UG9gF/

于 2012-08-20T21:19:45.563 回答
2

JavaScript 没有块作用域,并且您只有一个original包含最后一个枚举函数的变量。

此解决方案不会更改上下文原型(主机对象!),而只会更改以下内容的副本myContext

var myContext = someCanvas.getContext('2d');
var CanvasRenderingContext2DPrototype = Object.getPrototypeOf(myContext);
for (var p in CanvasRenderingContext2DPrototype) (function(original, prop) {
    myContext[prop] = function() {
        // some extra code
        original.apply(myContext, arguments);
    };
})(CanvasRenderingContext2DPrototype[p], p);
于 2012-08-20T21:22:29.420 回答