1

I was looking at w3schools web worker page, and noticed this code:

var i=0;

function timedCount()
{
i=i+1;
postMessage(i);
setTimeout("timedCount()",500);
}

timedCount(); 

Two questions:

  1. Is this considered a recursive function?
  2. If it is, is it resource-intensive?

I'm not fully clear on the nature of recursive functions yet, but I remember hearing that every recursive call gets stored in the memory somewhere. Is this true for all recursive functions? Will that function eventually clog up the memory if it runs for long enough?

Thanks!

4

3 回答 3

4

不是递归的,因为timedCount在调用下一个实例之前退出。如果你想这样称呼它,它只是一个自我延续的延迟循环。setInterval(顺便说一句,使用而不是重复使用会更好地处理setTimeout。该示例是一些非常糟糕的代码,大多数W3Fools资源也是如此。)

timedCount() -> setTimeout() -> end
    ^                |
    |                |
    +----------------+

是一个递归函数:

function recurse() {
    recurse();
}

这里建立了一个调用堆栈,外部调用recurse不会退出堆栈,直到内部recurse调用返回,内部调用返回才会返回,recurse等等。无限。由于这里没有return任何地方,这最终会破坏堆栈;所以有你的资源使用。

recurse() -> recurse() -> recurse() -> recurse() -> recurse() -> ...
于 2013-07-22T14:49:01.493 回答
2

通常可以优化递归,但您可以放心地假设 javascript 实现不会对递归进行优化。

关于你的两个具体问题:

  1. 这不是严格的递归函数。递归函数在函数体的某处调用自身。函数 timedCount 总是返回控制并且从不直接或间接地调用它自己。在这种情况下,它将控制权返回给页面的事件循环,以便稍后由计时器再次调用。
  2. 这意味着它确实会尝试确保自己会再次被调用,但是因为它没有直接调用自己,所以它不会填满堆栈空间。因此,它不会随着时间的推移堵塞内存。

timedCount 的重要之处在于它在返回之前不能再次调用。不考虑并行性。

于 2013-07-22T14:56:48.927 回答
1

每个函数都在某个地方的内存中。

真正的递归函数每次调用都会消耗堆栈空间(就像其他所有函数一样),重要的是它递归了多少次。

我不考虑示例“递归”,因为原始调用在计时器到期后再次调用之前timedCount 结束。如果它看起来像这样:

function timedCount() {
  i = i + 1;
  postMessage(i);
  timedCount();
}

那将是递归的,并且由于没有终止条件,因此会很快耗尽您的堆栈。

于 2013-07-22T14:47:16.280 回答