在声明时调用 Javascript 匿名函数不起作用,稍后调用它
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8583548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
calling a Javascript anonymous function right when it's declared, doesn't work, calling it later does
提问by Petruza
[answered]
[answered]
I'm testing my browser's fps for an html5 game.
I have this code:
我正在为 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 );
})();
It gives the following error on Chrome:Uncaught Error: TYPE_MISMATCH_ERR: DOM Exception 17
On line #27: requestAnimationFrame( step );
它在 Chrome 上出现以下错误:Uncaught Error: TYPE_MISMATCH_ERR: DOM Exception 17
在线 #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
W3 说这个错误是:If the type of an object is incompatible with the expected type of the parameter associated to the object.
但我实际上根本没有与 DOM 交互,除了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();
但是,如果我删除分配给的匿名函数的调用括号,step
而只是声明该函数,然后在新行中放置:step();
It works.
Why is this?
Shouldn't both work the same?
有用。
为什么是这样?
两者的工作方式不应该一样吗?
回答by Felix Kling
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.
requestAnimationFrame
期望一个函数,但在您的代码中,step
它不是一个函数,这是undefined
因为您没有从自调用函数中返回任何值。
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.
如果去掉调用括号,则step
确实是一个函数。
Please see @Martin's comment to this answer. I was referring to the fact that step
is undefined
afterthe function is executed, but of course it is also undefined
when you invoke the function the first time.
请参阅@Martin 对此答案的评论。我指的step
是undefined
在函数执行之后的事实,当然这也是undefined
您第一次调用函数的时候。
回答by Greg Hewgill
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.
现在没有匿名函数(除了小回退函数),它只是运行的代码。您可以对您的step()
函数应用类似的简化。
回答by Jonathan M
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 );
};
回答by nnnnnn
Your current code essentially says "run this anonymous function and assign its return value to step
". There are two basic problems with this:
您当前的代码基本上是说“运行此匿名函数并将其返回值分配给step
”。这有两个基本问题:
- The function doesn't return a value, so even after it runs
step
will be undefined. - Even if the function did return a value, you are trying to use
step
insidethe function the first time it runs, at which point the assignment tostep
has not yet taken place.
- 该函数不返回值,因此即使在它运行之后也
step
将是未定义的。 - 即使函数确实返回了一个值,您也试图在函数第一次运行时在函数
step
内部使用,此时step
尚未进行赋值。
The simplest way to fix this is what you already did, i.e., declare step
as a function and then run it on the next line:
解决此问题的最简单方法是您已经执行的操作,即声明step
为函数,然后在下一行运行它:
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.
不幸的是,IE 不太擅长命名函数表达式。
And also unfortunately (unfortunate from my point of view, anyway) arguments.callee
is now deprecated and won't work in strict mode.
而且不幸的是(无论如何,从我的角度来看很不幸)arguments.callee
现在已被弃用,并且无法在严格模式下工作。
回答by Tyler Crompton
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.
我看到了几个问题。您正在为 step 分配匿名函数的返回值。然而,当您删除括号时。您正在使 step 成为一个功能。由于您没有在匿名函数中返回值,step
因此undefined
. 因此,您将收到类型错误。我会删除最后的括号。