详解JS函数stack size计算方法


Posted in Javascript onJune 18, 2018

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

如果你写了一个一直调用自身的死循环,那么恭喜你,很快就可以看到报错: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();
 };
}());
Javascript 相关文章推荐
JavaScript中两种链式调用实现代码
Jan 12 Javascript
利用jq让你的div居中的好方法分享
Nov 21 Javascript
给应用部分的js代码设定一个统一的入口
Jun 15 Javascript
JavaScript中的Number数字类型学习笔记
May 26 Javascript
jquery实现拖动效果
Aug 10 Javascript
javascript阻止事件冒泡和浏览器的默认行为
Jan 21 Javascript
Angular4编程之表单响应功能示例
Dec 13 Javascript
vue 实现axios拦截、页面跳转和token 验证
Jul 17 Javascript
vue动态设置img的src路径实例
Sep 18 Javascript
用Fundebug插件记录网络请求异常的方法
Feb 21 Javascript
JS正则表达式常见函数与用法小结
Apr 13 Javascript
js实现随机点名
Jan 19 Javascript
jQuery使用动画队列自定义动画操作示例
Jun 16 #jQuery
node.js自动上传ftp的脚本分享
Jun 16 #Javascript
Vue中props的使用详解
Jun 15 #Javascript
基于jQuery实现的设置文本区域的光标位置
Jun 15 #jQuery
深入浅析Vue全局组件与局部组件的区别
Jun 15 #Javascript
react-native android状态栏的实现
Jun 15 #Javascript
JS实现监控微信小程序的原理
Jun 15 #Javascript
You might like
Syphon 使用方法
2021/03/03 冲泡冲煮
php AJAX实例根据邮编自动完成地址信息
2008/11/23 PHP
探讨PHP调用时间格式的参数详解
2013/06/06 PHP
php unset全局变量运用问题的深入解析
2013/06/17 PHP
php开发微信支付获取用户地址
2015/10/04 PHP
Yii操作数据库实现动态获取表名的方法
2016/03/29 PHP
php 数组元素快速去重
2017/05/05 PHP
php实现页面纯静态的实例代码
2017/06/21 PHP
Javascript insertAfter() 实现函数代码
2011/10/12 Javascript
使用Java实现简单的server/client回显功能的方法介绍
2013/05/03 Javascript
如何实现textarea里的不同文本显示不同颜色
2014/01/20 Javascript
javascript面向对象之定义成员方法实例分析
2015/01/13 Javascript
js智能获取浏览器版本UA信息的方法
2016/08/08 Javascript
jquery dataview数据视图插件使用方法
2016/12/23 Javascript
微信小程序商品到详情的实现
2017/06/27 Javascript
Vue.js devtool插件安装后无法使用的解决办法
2017/11/27 Javascript
[04:26]DOTA2上海特锦赛小组赛第二日 TOP10精彩集锦
2016/02/27 DOTA
Python字符串的encode与decode研究心得乱码问题解决方法
2009/03/23 Python
Python爬虫爬取新浪微博内容示例【基于代理IP】
2018/08/03 Python
详解python如何在django中为用户模型添加自定义权限
2018/10/15 Python
Python cookie的保存与读取、SSL讲解
2020/02/17 Python
Django models filter筛选条件详解
2020/03/16 Python
ITK 实现多张图像转成单个nii.gz或mha文件案例
2020/07/01 Python
HTML5 通信API 跨域门槛将不再高、数据推送也不再是梦
2013/04/25 HTML / CSS
日本钓鱼渔具和户外用品网上商店:naturum
2016/08/07 全球购物
西班牙国家航空官方网站:Iberia
2017/11/16 全球购物
请写出一段Python代码实现删除一个list里面的重复元素
2015/12/29 面试题
护理人员的自我评价分享
2014/03/15 职场文书
大学活动总结格式
2014/04/29 职场文书
教师先进工作者事迹材料
2014/05/01 职场文书
社区爱国卫生月活动总结
2014/06/30 职场文书
观看《杨善洲》宣传教育片心得体会
2016/01/23 职场文书
2019初中学生入团申请书
2019/06/27 职场文书
Pytorch 统计模型参数量的操作 param.numel()
2021/05/13 Python
python中urllib包的网络请求教程
2022/04/19 Python
Java Redisson多策略注解限流
2022/09/23 Java/Android