在es6中阅读了递归尾部调用优化的Dr Rauschmayer's description之后,我一直在尝试重新创建他详细介绍的递归阶乘函数的“零堆栈”执行。
使用Chrome调试器在堆栈帧之间切换,我发现没有进行尾部优化,并且正在为每个递归创建堆栈帧。
我还尝试通过不使用调试器的函数来测试优化,而是将100000
传递给阶乘函数。这将引发“最大堆栈”错误,这实际上表明未对其进行优化。
这是我的代码:
const factorial = (n, acc = 1) => n <= 1 ? acc : factorial(n - 1, n * acc)
console.log( factorial(100000) )
结果:
Uncaught RangeError: Maximum call stack size exceeded
最佳答案
V8是Chrome中的JavaScript引擎,已经有一段时间支持TCO了,但是截至本更新答案(2017年11月)以来,它不再支持TCO,而在撰写本文时,V8中没有关于TCO的积极开发,也没有任何计划。您可以在the V8 tracking bug for it中阅读详细信息。
TCO支持在V8中似乎已经达到了一个不错的水平,但由于几个原因(调试问题,错误)而仍然落后。但是随后发生了几件事,不仅是the V8 team raised significant issues with TCO并强烈支持称为syntactic tail calls (STCs)的规范更改,这要求在源代码中有意标记尾调用(例如return continue doThat();
)。但是,该提案于2017年7月成为inactive。同样在7月份,由于没有进行TCO工作,V8团队从TurboFan *的源代码中删除了支持TCO的代码,否则它会受到破坏。 (例如,成为维护难题和错误源。)
因此,目前(2017年11月)尚不清楚V8中是否会出现“隐形” TCO,是否会出现某种类型的STC或什么。为此,Chrome Platform Status page表示Mozilla(Firefox/SpiderMonkey)和Microsoft(Edge/Chakra)支持TCO的“混合”公共(public)信号,Safari随TCO一起提供,并且Web开发人员对该功能表示“肯定”。我们将看到我们从这里出发的去向。如果有的话。
*(TurboFan = V8中当前的最先进JIT编译器,现在他们已经从Full-Codegen [JIT] +曲轴[积极优化JIT]到点火[解释器+]和TurboFan [积极优化JIT] switched)