截至2019年2月,Mac上的Chrome版本为71.0.3578.98
,以下程序将Uncaught RangeError: Maximum call stack size exceeded error.
的计数抛出16516
。
const a = x => {
console.log(x)
a(x + 1)
}
a(1)
我已经做了很多谷歌搜索,但是找不到有关Chrome或其他浏览器对尾部呼叫优化(TCO)支持的任何文章,也没有找到实现它的任何未来计划。
我的两个问题是:
我发现的帖子大多是过时的(2016年或更早)或令人困惑。例如https://www.chromestatus.com/feature/5516876633341952
答案 0 :(得分:4)
TCO,或者说JavaScript中的尾叫 Elimination (在讨论中通常也称为“正确尾叫(PTC)”)是一个漫长而可悲的故事。
2011年左右,TC39(JavaScript标准委员会)决定在即将到来的ES6标准中采用强制性TCE,并得到所有主要浏览器供应商的一致同意。
2015年,正式采用了新标准,名称为EcmaScript2015。这时,实际上没有任何浏览器实现过TCE,这主要是因为ES2015中有太多新功能被认为更重要而无法使用。 (今天,ES6尚不存在JS功能建议及其采用的过程,其中包括在生产引擎中实现两种实现的要求。)
2016年初,Safari和Chrome都实施了TCE。 Safari宣布发货,而Chrome则将其保留为“实验功能”标志。其他浏览器(Firefox和Internet Explorer / Edge)也开始对其进行调查,并产生了新的想法。讨论最终演变为这是否是一个可行的功能。 Edge在为Windows ABI高效实现它方面遇到问题,Firefox担心开发人员从堆栈跟踪中调用“丢失”的体验(此问题已在2011年进行了详细讨论)。
为了解决上述问题,同时挽救了电话尾部功能,包括Chrome和Edge团队在内的数名成员建议进行电话尾部 explicit ,即要求return语句为带有附加关键字的注释,以加入尾调用语义。这些所谓的“ syntactic tail calls”(STC)是在Chrome中实现的,作为概念证明。
在2016年5月的TC39会议上,几乎一整天都在不解决的情况下广泛讨论了尾叫问题。 Firefox和Edge明确表示,它们将不执行标准中指定的TCE。 Firefox成员建议将其取出。 Safari和Chrome对此并不认同,Safari团队明确表示他们无意取消TCE。语法尾部调用的提议也被拒绝,尤其是Safari。委员会陷入僵局。您可以阅读meeting notes of this discussion。
据我所知,从技术上讲,这种僵局今天仍然存在。但是,实际上,对JavaScript的尾调用几乎已死,并且尚不清楚它们是否会回来。至少那是灾难性会议后Chrome小组的结论,这导致决定从Chrome删除尾部调用的实现,以简化引擎并防止钻头腐烂。它们仍然可以在Safari中使用。
披露:直到2017年,我还是TC39和Chrome / V8团队的一员,所以我的看法可能有偏见。
答案 1 :(得分:1)
即使对于TCO来说,对我们所有人来说都是梦dream以求的,通过使用trampoline
技术,您可以轻松地将代码转换为运行,就好像它是尾部优化的一样。
const a = x => {
if(x > 500000) {
console.log(x);
return;
}
return ()=> a(x + 1); //you return a function, it hasn't been called yet
}
const trampoline = fn => (...args) => {
let result = fn(...args)
//repeatedly call the function till you hit your base case
while (typeof result === 'function') {
result = result();
}
return result;
}
var t = trampoline(a);
t(1);