Safari中尾调用优化(TCO)未生效?尾递归阶乘测试报栈溢出
问题根因
你遇到的问题是遗漏了ES6规范规定的TCO(尾调用优化)生效的核心前提,并非Safari的实现存在缺陷。
TCO生效的强制要求
- 必须启用严格模式(Strict Mode)
这是ES6规范明确的TCO触发必要条件:非严格模式下为了兼容旧代码遗留的arguments对象、函数caller属性,引擎必须保留外层函数的完整栈帧,无法将其销毁复用为尾调用的栈帧,因此直接禁用TCO优化。你当前的测试代码没有任何严格模式声明,默认运行在非严格模式下,36000次递归直接撑爆调用栈,抛出RangeError。如果在Safari控制台直接粘贴代码测试,必须手动添加严格模式声明,控制台默认运行在非严格模式环境。
- 尾调用位置必须符合规范
你写的三元表达式分支中的factorial调用本身符合尾位置要求:函数最终返回值就是该调用的返回结果,没有额外运算操作,这部分没有问题。
正确测试代码调整方案
在代码顶部添加严格模式声明即可触发TCO:
'use strict' function factorial(n, r = 1n) { return (n <= 1) ? r : factorial(n - 1n, n * r) } console.log(factorial(36000n))
如果使用ES模块加载代码(<script type="module">),模块默认处于严格模式,无需额外添加'use strict'声明,直接运行原递归逻辑即可正常执行,不会触发栈溢出。
常见误区
ES兼容性表中标注的Safari支持TCO,指的是实现了规范要求的严格模式下的TCO能力,而非非严格模式下的兼容优化,这是多数开发者踩坑的核心原因。
内容的提问来源于stack exchange,提问作者kornieff
相关产品推荐
相关产品推荐

