3

[answered]

HTML5 ゲームのブラウザの fps をテストしています。
私はこのコードを持っています:

var requestAnimationFrame = ( function() {
    return window.requestAnimationFrame || //Chromium 
    window.webkitRequestAnimationFrame || //Webkit
    window.mozRequestAnimationFrame || //Mozilla Geko
    window.oRequestAnimationFrame || //Opera Presto
    window.msRequestAnimationFrame || //IE Trident?
    function(callback) { //Fallback function
        window.setTimeout(callback, 1000/60);
    }
})();

var hits = 0;
var last = new Date().getTime();

var step = (function(){
    now = new Date().getTime();
    hits += 1;
    if( now - last >= 1000 ){
        last += 1000;
        console.log( "fps: "+ hits );
        hits = 0;
    }
    requestAnimationFrame( step );
})();

Chrome で次のエラーが発生します:
Uncaught Error: TYPE_MISMATCH_ERR: DOM Exception 17
行番号 27:requestAnimationFrame( step );

W3 は、このエラーは次If the type of an object is incompatible with the expected type of the parameter associated to the object.
のように述べています。window

しかし、割り当てられた無名関数の呼び出し括弧を削除しstep、代わりにその関数を宣言し、新しい行に次のように記述した場合:
step();

できます。
どうしてこれなの?
どちらも同じように機能するべきではありませんか?

4

5 に答える 5

11

requestAnimationFrame関数を期待していますが、コードでstepは関数ではありません。これはundefined、自己呼び出し関数から値を返さないためです。

var step = (function(){
    // this code is executed immediately, 
    // the return value is assigned to `step` 
})();

呼び出し括弧を削除すると、step実際に関数になります。

この回答に対する@Martinのコメントをご覧ください。関数が実行された後ということですstepが、もちろん最初に関数を呼び出すときもそうです。undefined undefined

于 2011-12-21T00:04:56.513 に答える
2

問題の中にはこれがあります(修正されました):

var step = function(){
    now = new Date().getTime();
    hits += 1;
    if( now - last >= 1000 ){
        last += 1000;
        console.log( "fps: "+ hits );
        hits = 0;
    }
    requestAnimationFrame( step );
};
于 2011-12-21T00:12:34.237 に答える
2

ここで何が起こっているのかについて、いくつかの根本的な誤解が見られます。たとえば、最初の宣言では次のようになります。

var requestAnimationFrame = ( function() {
    return window.requestAnimationFrame || //Chromium 
    window.webkitRequestAnimationFrame || //Webkit
    window.mozRequestAnimationFrame || //Mozilla Geko
    window.oRequestAnimationFrame || //Opera Presto
    window.msRequestAnimationFrame || //IE Trident?
    function(callback) { //Fallback function
        window.setTimeout(callback, 1000/60);
    }
})();

匿名関数を作成し、すぐにそれを呼び出して、結果を変数に代入しています。これの要点がわかりません。以下は同様にうまく機能します。

var requestAnimationFrame = 
    window.requestAnimationFrame || //Chromium 
    window.webkitRequestAnimationFrame || //Webkit
    window.mozRequestAnimationFrame || //Mozilla Geko
    window.oRequestAnimationFrame || //Opera Presto
    window.msRequestAnimationFrame || //IE Trident?
    function(callback) { //Fallback function
        window.setTimeout(callback, 1000/60);
    };

現在、無名関数はありません (小さなフォールバック関数を除いて)、実行されるのはコードだけです。同様の単純化をstep()関数に適用できます。

于 2011-12-21T00:10:29.367 に答える
1

あなたの現在のコードは本質的に「この匿名関数を実行し、その戻り値を割り当てます」と言っていますstep。これには 2 つの基本的な問題があります。

  1. 関数は値を返さないため、実行後stepも未定義になります。
  2. 関数が値を返したとしても、最初の実行時に関数step stepで使用しようとしており、その時点では割り当てがまだ行われていません。

これを修正する最も簡単な方法は、すでに行ったことです。つまり、step関数として宣言してから、次の行で実行します。

var step = function() { ... };
step();

または、名前付き関数式を使用できます。

(function step() {
   ...
   requestAnimationFrame( step );
})();

これは次と同等です:

(function () {
    ...
    requestAnimationFrame( arguments.callee );
})();

残念ながら、IE は名前付き関数式が得意ではありません

また、残念なことに (とにかく残念なことに、私の観点からは)arguments.calleeは非推奨になり、strict モードでは動作しません。

于 2011-12-21T00:21:36.690 に答える
1

いくつかの問題があります。step に無名関数の戻り値を割り当てています。一方、括弧を削除すると。ステップを関数にしています。無名関数で値を返さないので、stepis undefined. したがって、型エラーが発生します。最後に括弧を削除します。

于 2011-12-21T00:07:10.690 に答える