【问题标题】:Asynchronous Javascript Recursion异步 Javascript 递归
【发布时间】:2013-06-13 23:04:17
【问题描述】:

我不知道如何问这个现在在我脑海里嗡嗡作响的问题,所以请耐心等待。我是异步编程的新手,我认为最好的学习方法是制作一个小的 javascript pong 游戏。我从一个 shootball() 函数开始,然后在另一个 div 周围反弹一个 div。我是如何做到这一点的:

function shootball(angle, speed){
    angle = (angle/360.0)*2*Math.PI;
    var ballmotion = setInterval(function(){
        var nowx, nowy, minusY, plusX;
        nowx = $("#ball").position().left;
        nowy = $("#ball").position().top;
        minusY = Math.sin(angle) * 4.0;
        plusX = Math.cos(angle) * 4.0;
        if(hitsWall(nowx+plusX, nowy-minusY)){
            clearInterval(ballMotion);
            shootball(newAngle(nowx+plusX, nowy-minusY), speed);
        }
        $("#ball").css("left", (nowx + plusX)).css("top", (nowy - minusY));
     }, 10/speed);
}

我不喜欢大量不必要的递归,但我只是想尝试一下。瞧,它完全按照我的预期工作。但是当我开始充实程序的其余部分时,我突然想到我无法避免这种递归性质。所以我的问题是:javascript 是否以某种方式认识到调用 clearInterval 后调用“shootball”函数基本上完成了?或者这真的会发现自己在我的堆栈中加载了不必要的激活记录?提前感谢您提供的任何专业知识。

【问题讨论】:

  • 您可以设置一个断点并查看调用堆栈;)
  • 如果一个函数的调用时间比间隔时间长,setInterval 会变得很糟糕,请考虑改用 setTimeout。另外,我确信您可以将大部分函数移到表达式之外,这样就不会每次都创建新的函数实例。
  • 我不完全确定,但我相信只要球没有撞到墙上,堆栈就会被清空。

标签: javascript asynchronous


【解决方案1】:

在调用 clearInterval 之后,javascript 是否以某种方式识别调用“shootball”函数基本上完成了?

不,shootball 早就完成了,就在分配给ballmotion 之后。但是,它的变量范围(anglespeedballmotion 和父范围)确实存在,因为匿名函数用它构建了一个闭包并从外部(从调度程序)引用。在clearInterval 调用删除对它的引用之后,该范围将被垃圾收集。

这真的会发现自己在我的堆栈中加载了不必要的激活记录吗?

没有。通过setTimeout/setInterval 执行的每个函数都在其自己的执行上下文中运行,并带有一个全新的调用堆栈。

【讨论】:

  • 变量可能不一定被清除,因为在某些浏览器中,只要页面正在运行,它们就会保持所有变量处于活动状态。
  • @Derek:你的意思是有些浏览器搞砸了clearInterval的垃圾收集?
  • 我不确定,但因为我不认为它是写在标准中的,所以浏览器不一定要清除无用的变量。
猜你喜欢
  • 2018-02-24
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 2015-07-02
  • 1970-01-01
  • 2021-08-28
  • 2015-10-30
相关资源
最近更新 更多