递归函数本质上是资源密集型的吗?

时间:2013-07-22 14:44:09

标签: javascript recursion

我正在查看w3schools网页工作者页面,并注意到此代码:

var i=0;

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

timedCount(); 

两个问题:

  1. 这被认为是递归函数吗?
  2. 如果是,是资源密集型吗?
  3. 我还不完全了解递归函数的本质,但我记得每次递归调用都存储在内存中。这适用于所有递归函数吗?如果它运行的时间足够长,那么该函数最终会阻塞内存吗?

    谢谢!

3 个答案:

答案 0 :(得分:4)

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

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

是一个递归函数:

function recurse() {
    recurse();
}

这里建立了一个调用堆栈,外部recurse将不会退出并离开堆栈,直到内部recurse调用返回,直到它的内部recurse调用返回等无限期。由于这里任何地方都没有return,所以这最终会炸掉堆栈;所以有资源使用。

recurse() -> recurse() -> recurse() -> recurse() -> recurse() -> ...

答案 1 :(得分:2)

一般来说,递归可以优化,但你可以放心地假设javascript实现没有为递归优化。

关于你的两个具体问题:

  1. 这不是严格意义上的递归函数。递归函数在函数体中的某处调用它自己。函数timedCount始终返回控件,从不直接或间接调用自身。在这种情况下,它将控制返回到页面的事件循环,以便稍后由计时器再次调用。
  2. 这意味着它确实会尝试确保自己再次被调用,但因为它没有直接调用自身,所以它不会填充堆栈空间。因此,它不会随着时间的推移而堵塞内存。
  3. timedCount的重要之处在于它在返回之前无法再次调用。 无视并行性。

答案 2 :(得分:1)

每个功能都在内存中。

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

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

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

这是递归的,因为没有终止条件,所以会非常快地炸掉你的筹码。