[回答]
我正在测试我的浏览器的fps以获得html5游戏 我有这段代码:
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.
但我实际上并没有与DOM进行交互,除了window
但是,如果我删除分配给step
的匿名函数的调用括号,而只是声明该函数并在新行上放置:
step();
有效。
这是为什么?
两者都不应该一样吗?
答案 0 :(得分:9)
requestAnimationFrame
需要一个函数,但在您的代码中,step
不是函数,它是undefined
,因为您不会从自调用函数返回任何值。< / p>
var step = (function(){
// this code is executed immediately,
// the return value is assigned to `step`
})();
如果删除了调用括号,那么step
确实是一个函数。
请参阅@ Martin对此答案的评论。我指的是{/ 1}}在执行函数后step
这一事实,但当你第一次调用函数时它当然也是undefined
。。
答案 1 :(得分: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()
函数应用类似的简化。
答案 2 :(得分:2)
问题包括(更正):
var step = function(){
now = new Date().getTime();
hits += 1;
if( now - last >= 1000 ){
last += 1000;
console.log( "fps: "+ hits );
hits = 0;
}
requestAnimationFrame( step );
};
答案 3 :(得分:1)
我看到了几个问题。您正在为步骤指定匿名函数的返回值。然而,当您删除括号时。你正在做一个功能。由于您未在匿名函数中返回值,step
为undefined
。因此,您将收到类型错误。我会在最后删除括号。
答案 4 :(得分:1)
您当前的代码基本上是“运行此匿名函数并将其返回值分配给step
”。这有两个基本问题:
step
之后也不会定义。step
,此时step
的赋值已经尚未发生。解决这个问题的最简单方法就是你已经做过的事情,即将step
声明为函数,然后在下一行运行它:
var step = function() { ... };
step();
或者您可以使用命名函数表达式:
(function step() {
...
requestAnimationFrame( step );
})();
相当于:
(function () {
...
requestAnimationFrame( arguments.callee );
})();
不幸的是IE isn't that great at named function expressions。
而且不幸的是(不幸的是,从我的观点来看,不管怎样)arguments.callee
现已弃用,并且无法在严格模式下运行。