在声明时调用 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 03:53:31  来源:igfitidea点击:

calling a Javascript anonymous function right when it's declared, doesn't work, calling it later does

javascripthtmlcanvasrequestanimationframe

提问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 stepand 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

requestAnimationFrameexpects a function, but in your code, stepis not a function, it is undefinedbecause 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 stepis indeed a function.

如果去掉调用括号,则step确实是一个函数。

Please see @Martin's comment to this answer. I was referring to the fact that stepis undefinedafterthe function is executed, but of course it is also undefinedwhen you invoke the function the first time.

请参阅@Martin 对此答案的评论。我指的stepundefined函数执行之后的事实,当然这也是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”。这有两个基本问题:

  1. The function doesn't return a value, so even after it runs stepwill be undefined.
  2. Even if the function did return a value, you are trying to use stepinsidethe function the first time it runs, at which point the assignment to stephas not yet taken place.
  1. 该函数不返回值,因此即使在它运行之后也step将是未定义的。
  2. 即使函数确实返回了一个值,您也试图在函数第一次运行时在函数step内部使用,此时step尚未进行赋值。

The simplest way to fix this is what you already did, i.e., declare stepas 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.calleeis 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, stepis undefined. Therefore, you will get a type error. I would remove the parentheses at the end.

我看到了几个问题。您正在为 step 分配匿名函数的返回值。然而,当您删除括号时。您正在使 step 成为一个功能。由于您没有在匿名函数中返回值,step因此undefined. 因此,您将收到类型错误。我会删除最后的括号。