专栏首页FundebugJS的函数调用栈有多深?

JS的函数调用栈有多深?

译者按: 有时候会遇到 Maximum call stack size exceeded 的问题,本文教你 stack size 的计算方法。

本文采用意译,版权归原作者所有

如果你写了一个一直调用自身的死循环,那么恭喜你,很快就可以看到报错:Uncaught RangeError: Maximum call stack size exceeded。那么这个 call stack size 有多少呢?

1. 计算方法

如下的方法可以为你计算出你使用的 JavaScript 引擎可以支持多深的调用(由 Ben Alman 的一段代码获得灵感):

function computeMaxCallStackSize() {
    try {
        return 1 + computeMaxCallStackSize();
    } catch (e) {
        // Call stack overflow
        return 1;
    }
}

运行得到如下三个结果:

  • Node.js: 11034
  • Firefox: 50994
  • Chrome: 10402

这些数字代表了什么呢?Mr.Aleph 告诉我在 V8,可调用的层数基于两个方面:1. 栈的大小;2. 每一栈帧的大小(用于记录函数参数和局部变量)。你可以在computeMaxCallStackSize声明局部变量来测试,你会发现数字变小。

2. ECMAScript 6 中尾递归优化

ECMAScript 6 支持尾递归优化:如果一个函数的最后一个操作是函数调用,那么将会用“跳转”而不是“子调用”。也就是说如果你将computeMaxCallStackSize重写成如下形式,在 ES6 的严格模式下,就会一直运行了。

function computeMaxCallStackSize(size) {
    size = size || 1;
    return computeMaxCallStackSize(size + 1);
}

3. 亮点评论

  • Andrei: “ECMAScript 6”版本的代码根本跑不通。虽然 size 会被更改,但是最终并没有值返回。
  • 回复 Andrei: 有趣!你不能用这段代码去计算 stack size。在 ES6 下,这段代码会一直运行,因此不会返回数据。在其它情况下,会返回 RangeError。为了使其工作,我把代码重写了一下:
var computeMaxCallStackSize = (function() {
    return function() {
        var size = 0;
        function cs() {
            try {
                size++;
                return cs();
            } catch (e) {
                return size + 1;
            }
        }
        return cs();
    };
})();

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有阳光保险、核桃编程、荔枝FM、掌门1对1、微脉、青团社等众多知名企业。欢迎大家免费试用

版权声明

转载时请注明作者Fundebug以及本文地址:

https://blog.fundebug.com/2018/06/15/call-stack-size/

原文链接:http://2ality.com/2014/04/call-stack-size.html

原文作者:Dr. Axel Rauschmayer

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JS的函数调用栈有多深?

    译者按: 有时候会遇到 Maximum call stack size exceeded 的问题,本文教你 stack size 的计算方法。

    Fundebug
  • JavaScript一团乱,这是好事

    为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

    Fundebug
  • 详解Vue的slot新用法

    最近发布不久的Vue 2.6,使用插槽的语法变得更加简洁。 对插槽的这种改变让我对发现插槽的潜在功能感兴趣,以便为我们基于Vue的项目提供可重用性,新功能和更清...

    Fundebug
  • JS的函数调用栈有多深?

    译者按: 有时候会遇到 Maximum call stack size exceeded 的问题,本文教你 stack size 的计算方法。

    Fundebug
  • 55. 比较字符串

    比较两个字符串A和B,确定A中是否包含B中所有的字符。字符串A和B中的字符都是 大写字母 样例 给出 A = "ABCD" B = "ACD",返回 tru...

    和蔼的zhxing
  • 递归与分治之棋盘覆盖问题

    在一个2^k * 2^k个方格组成的棋盘中,若有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘。 显然特殊方格在棋盘上出现的位置有4^...

    欠扁的小篮子
  • Oracle SGA 自动管理特性(sga_target参数)

        最近有网友对Oracle SGA内存自动管理特性不是很清楚,可能是由于当时翻译的 Oracle 10g SGA 的自动化管理 比较生涩,下面依旧是针对这...

    Leshami
  • 【计算机本科补全计划】指令:计算机的语言(MIPS) Part4

    正文之前 这几天陪人玩去了,所以没怎么看书。今早某人回家了。所以我也就可以一个人继续开始在图书馆的浪荡之路了。爽歪歪!!!!而且可以一个人独占温暖的地方,实在...

    用户1687088
  • [剑指offer] 滑动窗口的最大值

    给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,...

    尾尾部落
  • Python学习之property

    Property函数创建了一个属性size,此时访问器函数被用做参数(先取值,再赋值)。尽管它们看起来像属性一样,但size的特性依旧取决于getSize和se...

    py3study

扫码关注云+社区

领取腾讯云代金券