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、最後に列挙された関数を含む変数は1つだけです。

このソリューションは、コンテキストプロトタイプ(ホストオブジェクト!)を変更しませんが、次のコピーのみを変更し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 に答える