[answered]
I'm testing my browser's fps for an html5 game.
I have this code:
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 );
})();
It gives the following error on Chrome:
Uncaught Error: TYPE_MISMATCH_ERR: DOM Exception 17
On line #27: requestAnimationFrame( step );
W3 says this error is: If the type of an object is incompatible with the expected type of the parameter associated to the object.
But I'm not actually interacting with the DOM at all, except for window
But if I remove the calling parentheses of the anonymous function assigned to step
and instead just declare that function and on a new line I put:
step();
It works.
Why is this?
Shouldn't both work the same?
requestAnimationFrame
expects a function, but in your code, step
is not a function, it is undefined
because you don't return any value from your self-invoking function.
var step = (function(){
// this code is executed immediately,
// the return value is assigned to `step`
})();
If you remove the calling parenthesis, then step
is indeed a function.
Please see @Martin's comment to this answer. I was referring to the fact that step
is undefined
after the function is executed, but of course it is also undefined
when you invoke the function the first time.
I see some fundamental misunderstanding of what's going on here. For example, in your first declaration:
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);
}
})();
You're creating an anonymous function, then immediately calling it and assigning the result to a variable. I don't see the point of this. The following would work equally well:
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);
};
There's no anonymous function now (well except for the little fallback function), it's just code that runs. You can apply a similar simplification to your step()
function.
Among the issues is this (corrected):
var step = function(){
now = new Date().getTime();
hits += 1;
if( now - last >= 1000 ){
last += 1000;
console.log( "fps: "+ hits );
hits = 0;
}
requestAnimationFrame( step );
};
I see a couple of issues. You are assigning step the return value of the anonymous function. Whereas, when you remove the parentheses. You are making step a function. Since you are not returning a value in the anonymous function, step
is undefined
. Therefore, you will get a type error. I would remove the parentheses at the end.
Your current code essentially says "run this anonymous function and assign its return value to step
". There are two basic problems with this:
step
will be undefined. step
inside the function the first time it runs, at which point the assignment to step
has not yet taken place. The simplest way to fix this is what you already did, ie, declare step
as a function and then run it on the next line:
var step = function() { ... };
step();
Or you could use a named function expression:
(function step() {
...
requestAnimationFrame( step );
})();
Which is the equivalent of:
(function () {
...
requestAnimationFrame( arguments.callee );
})();
Unfortunately IE isn't that great at named function expressions .
And also unfortunately (unfortunate from my point of view, anyway) arguments.callee
is now deprecated and won't work in strict mode.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.