有任何JavaScript引擎进行尾调用(TCO)优化吗?
JavaScript引擎是否优化尾调用(TCO)的问题产生的原因是,ECMAScript 4规范最初计划添加对TCO的支持,但后来被取消了。截至2010年,目前没有广泛可用的JavaScript实现自动进行TCO。
然而,也有一些更新的信息。例如,Rhino引擎在“解释”模式(opt = -1)下具有自动TCO的功能。此外,ECMAScript 6已经包含了TCO,规范中称之为Proper Tail Calls。
然而,累加器模式并不能实现与TCO相同的效果。它只是将递归算法转换为尾递归形式。这是实现TCO的先决条件,但并不能替代TCO。在不优化尾调用的语言中,仍然会出现堆栈溢出的问题。
因此,尽管一些较新的JavaScript引擎支持TCO,但并没有广泛可用的实现。第二个链接提到的信息可能已经过时。
目前(18-07-2019),以下JavaScript引擎支持尾调用优化:
- Safari >= 10
- iOS >= 10
- Kinoma XS6
- Duktape 2.3
如果打开了"experimental JavaScript features"标志,则支持:
- Node 6.5
- Chrome 54 / Opera 41(当前版本的兼容表不再列出)
尾调用优化将在未来的ECMAScript 6严格模式中得到支持。有关详情,请参阅http://www.2ality.com/2015/06/tail-call-optimization.html。您可以在http://kangax.github.io/compat-table/es6/上查看当前引擎的支持情况。
JavaScript引擎是否进行尾调用优化(TCO)的问题主要是因为在Harmony(ECMAScript第6版)中计划引入了 proper tail calls。虽然目前尚未实现,但这给了人们希望。
此问题特指浏览器,而不是所有的ECMAScript实现。尽管问题标题使用了更通用的“JavaScript引擎”一词,但问题正文中明确指出“是否有(全部?)浏览器可能出现堆栈溢出异常”。
有人认为问题是关于两者的,但这并不使回答过时。
据我所知,Node使用与Chrome相同的v8版本,目前不支持TCO。可以通过一个简单的测试来证明,Node v0.12.7中的无限递归函数会导致“RangeError: Maximum call stack size exceeded”异常。
尽管有人期待JavaScript引擎实现TCO,目前大多数浏览器和Node都不支持该优化。希望在Harmony中引入proper tail calls后,这个问题会得到解决。