【问题标题】:Javascript game loop state in an anonymous function匿名函数中的 Javascript 游戏循环状态
【发布时间】:2023-10-12 15:02:02
【问题描述】:

我在画布上乱七八糟,从阅读一堆游戏循环 sn-ps/帖子开始,并将它们组合成最好的。

我今天遇到了这个 sn-p(它是 a post 的一部分,所以他们稍后会对其进行进一步的迭代。但我正在整合这些想法),但这让我有点困惑。

Game.run = (
    function() {
        var loops = 0;
        var skipTicks = 1000 / Game.fps;
        var maxFrameSkip = 10;
        var nextGameTick = (new Date).getTime();

        return function {
            loops = 0;

            while ((new Date).getTime() > nextGameTick && loops < maxFrameSkip) {
                Game.update();
                nextGameTick += skipTicks;
                loops++;
            }

            Game.draw();
        };
    }
)();

Game._intervalId = setInterval(Game.run, 1000 / Game.fps);

所以Game.run 被分配了外部函数的结果,也就是内部函数。但是内部函数依赖于nextGameTick,它是在外部函数中定义的...

那么这个游戏会在外部匿名函数中保持它的状态吗?如果是这样,有什么想法他们为什么这样做?

至于例如loops,每次调用都设置为0,是不是在外面声明,避免每次都重新声明变量?

【问题讨论】:

  • while 循环会让你的游戏变得不稳定。
  • @Shmiddty:是的,我想它会的。正如我所提到的,这是从the tutorial 中途的未完成循环。我认为这些代码中的任何一个都不会最终出现在最终版本中。不过出于好奇,我假设您说这会很不稳定,因为多个更新调用是在单个 while 循环中运行的,而不会返回它们之间的 UI?是这个原因,还是有其他原因?
  • 基本上,是的。但更不用说调用 update 了,更多的是在 while 循环完成之前它不会将控制权释放给 UI。我什至不确定代码是否正在向 UI 释放控制权,因为我没有看到超时、间隔或 requestAnimationFrame。
  • 啊,我想我错过了以下行,它实际上使用了 Game.run 方法:Game._intervalId = setInterval(Game.run, 1000 / Game.fps); 我会为后代编辑这个问题。谢谢!

标签: javascript scope html5-canvas anonymous-function


【解决方案1】:

这种类型的构造称为立即调用的函数表达式IIFE

此模式用于管理范围。在这种情况下,我们正在防止像 loopsskipTicks 这样的变量泄漏到全局范围内。更重要的是,它们被捕获在内部函数的闭包中,因此在对该内部函数的调用中持续存在。通过使用 IIFE,只有我们的内部函数可以看到这个状态,并且它在全局上下文中是隐藏的。

这是模式上的decent article。请特别参阅关于使用闭包保存状态的部分。

【讨论】:

    【解决方案2】:

    会的。

    您返回的函数的 local frame 在 Game.run 函数的 local frame 内。因此,在 Game.run 中围绕您返回的函数发生更改的任何变量都是持久的。每当您尝试引用 nextTick 变量时,该函数的父框架将在 Game.run 内部查看。

    【讨论】: