在JavaScript中调用递归函数

时间:2011-08-17 17:26:41

标签: javascript recursion

我知道你在JavaScript中对函数进行递归调用时应该轻率一点,因为你的第二次调用可能会慢10倍。

Eloquent JavaScript州:

  

有一个重要问题:在大多数JavaScript实现中,第二个版本比第一个版本慢大约10倍。在JavaScript中,运行一个简单的循环要比多次调用一个函数便宜很多。

John Resig甚至在this帖子中说这是一个问题。

我的问题是:为什么使用递归这么低效?它只是特定引擎的构建方式吗?我们是否会在JavaScript中看到时间不是这样的?

2 个答案:

答案 0 :(得分:11)

由于更改堆栈和设置新上下文等所有开销,函数调用比简单循环更昂贵。为了使递归非常有效,语言必须支持某种形式的尾部调用消除,这基本上意味着将某些类型的递归函数转换为循环。像OCaml,Haskell和Scheme这样的函数式语言就是这样做的,但是我所知道的JavaScript实现并没有这样做(除非他们都这样做,否则它只会有点用处,所以也许我们有餐饮哲学家的问题)。

答案 1 :(得分:3)

这只是构建浏览器使用的特定JS引擎的方式,是的。如果没有尾部调用消除,你必须在每次递归时创建一个新的堆栈帧,而使用循环它只是将程序计数器设置回它的开始。例如,Scheme将此作为语言规范的一部分,因此您可以以这种方式使用递归而不必担心性能。

https://bugzilla.mozilla.org/show_bug.cgi?id=445363表示在Firefox中取得了进展(Brendan Eich在这里谈到它可能是ECMAScript规范的一部分),但我认为目前的任何浏览器都没有实现这一点