正确调用Javascript匿名函数时';s声明,不';不行,以后再打会好的
[答] 我正在为html5游戏测试浏览器的fps。正确调用Javascript匿名函数时';s声明,不';不行,以后再打会好的,javascript,html,canvas,requestanimationframe,Javascript,Html,Canvas,Requestanimationframe,[答] 我正在为html5游戏测试浏览器的fps。 我有以下代码: var requestAnimationFrame = ( function() { return window.requestAnimationFrame || //Chromium window.webkitRequestAnimationFrame || //Webkit window.mozRequestAnimationFrame || //Mozilla Geko window.oR
我有以下代码:
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上出现以下错误:未捕获错误:类型不匹配\u错误:DOM异常17
第27行:
requestAnimationFrame(步骤)代码>
W3表示此错误为:如果对象的类型与与与该对象关联的参数的预期类型不兼容。
但是,除了窗口
但是如果我删除分配给step
的匿名函数的调用括号,而只是声明该函数,并在新的一行输入:
step()代码>
它起作用了。
这是为什么?
这两个函数不应该工作相同吗?requestAnimationFrame
需要一个函数,但在代码中,step
不是一个函数,它是未定义的,因为您不从自调用函数返回任何值
var step = (function(){
// this code is executed immediately,
// the return value is assigned to `step`
})();
如果删除调用括号,那么步骤实际上是一个函数
var step = (function(){
// this code is executed immediately,
// the return value is assigned to `step`
})();
请参阅@Martin对该答案的评论。我指的是,执行函数后,步骤
是未定义的
,但是当您第一次调用函数时,它当然也是未定义的。我看到了几个问题。您正在为步骤指定匿名函数的返回值。然而,当删除括号时。您正在使步骤成为一个函数。由于您没有在匿名函数中返回值,步骤
是未定义的
。因此,您将得到一个类型错误。我会去掉结尾的括号。我看到一些关于这里发生的事情的基本误解。例如,在您的第一次声明中:
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()
函数进行类似的简化。其中的问题如下(已更正):
var step = (function(){
// this code is executed immediately,
// the return value is assigned to `step`
})();
您当前的代码本质上是“运行此匿名函数并将其返回值分配给步骤
”。这有两个基本问题:
该函数不返回值,因此即使在运行步骤之后
也将未定义
即使函数确实返回了一个值,您也会在函数第一次运行时尝试在函数内部使用步骤
,此时尚未对步骤
进行赋值
修复此问题的最简单方法是您已经执行的操作,即将步骤
声明为函数,然后在下一行运行它:
var step = function() { ... };
step();
也可以使用命名函数表达式:
(function step() {
...
requestAnimationFrame( step );
})();
这相当于:
(function () {
...
requestAnimationFrame( arguments.callee );
})();
不幸的是
而且不幸的是(无论如何,从我的观点来看,这是不幸的)现在已经被弃用,无法在严格模式下工作。它似乎在FireFox中工作。运行时,FireBug显示mozRequestAnimationFrame()
函数对象。编辑:再看一下你的代码,为什么你要在步骤的赋值中传递步骤?我认为这本质上是在引用构造函数中对象的实例。。。您所做的看起来有点像在的示例,但步骤更简单地被声明为一个函数…+1,即使步骤在被调用时没有定义,但在调用后它仍然没有定义,因为立即函数不返回任何内容。@Martin:对,我实际上是指这个问题,甚至没有注意到调用函数时它也是未定义的。谢谢谢谢现在很明显,但我没有看到。DOM
错误分散了我的注意力。你是对的,这里不需要使用匿名函数。我假设代码是@FelixKling:Good catch的某个变体。复制粘贴编程规则!你说得对,我是复制粘贴的受害者,但你说的更有意义。你将步骤分配给函数的结果,而不是函数本身。我在这里的更正将函数分配到步骤
。哦,对了,你的注释会比代码更好地解释它。谢谢