详解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 相关文章推荐
js 实现的可折叠留言板(附源码下载)
Jul 01 Javascript
jquery实现动态操作select选中
Feb 11 Javascript
EasyUI实现第二层弹出框的方法
Mar 01 Javascript
JS实现超简单的鼠标拖动效果
Nov 02 Javascript
jQuery插件ajaxFileUpload使用详解
Jan 10 Javascript
js实现手机web图片左右滑动效果
Dec 29 Javascript
vue+jquery+lodash实现滑动时顶部悬浮固定效果
Apr 28 jQuery
webpack3里使用uglifyjs压缩js时打包报错的解决
Dec 13 Javascript
基于Webpack4和React hooks搭建项目的方法
Feb 05 Javascript
浅析vue中的MVVM实现原理
Mar 04 Javascript
Vue插槽原理与用法详解
Mar 05 Javascript
D3.js(v3)+react 实现带坐标与比例尺的散点图 (V3版本)
May 09 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
用PHP生成自己的LOG文件
2006/10/09 PHP
配置php.ini实现PHP文件上传功能
2014/11/27 PHP
PHP访问Google Search API的方法
2015/03/05 PHP
php中遍历二维数组并以表格的形式输出的方法
2017/01/03 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
laravel validate 设置为中文的例子(验证提示为中文)
2019/09/29 PHP
firefox中JS读取XML文件
2006/12/21 Javascript
javascript 表单验证常见正则
2009/09/28 Javascript
JavaScript 对象链式操作测试代码
2010/04/25 Javascript
js查找某元素中的所有图片地址的方法
2014/01/16 Javascript
js锁屏解屏通过对$.ajax进行封装实现
2014/07/31 Javascript
PHP结合jQuery实现红蓝投票功能特效
2015/07/22 Javascript
BootStrap 获得轮播中的索引和当前活动的焦点对象
2017/05/11 Javascript
Node.JS文件系统解析实例详解
2017/05/15 Javascript
微信小程序url传参写变量的方法
2018/08/09 Javascript
jsonp跨域及实现百度首页联想功能的方法
2018/08/30 Javascript
JavaScript如何实现元素全排列实例代码
2019/05/14 Javascript
javascript 数组精简技巧小结
2020/02/26 Javascript
[05:17]DOTA2誓师:今天我们在这里 明天TI4等我!
2014/03/26 DOTA
Pandas DataFrame 取一行数据会得到Series的方法
2018/11/10 Python
Python学习笔记之图片人脸检测识别实例教程
2019/03/06 Python
Python实现word2Vec model过程解析
2019/12/16 Python
python中的itertools的使用详解
2020/01/13 Python
django rest framework serializer返回时间自动格式化方法
2020/03/31 Python
使用keras实现densenet和Xception的模型融合
2020/05/23 Python
Python爬虫防封ip的一些技巧
2020/08/06 Python
基于python的opencv图像处理实现对斑马线的检测示例
2020/11/29 Python
详解CSS3中nth-child与nth-of-type的区别
2017/01/05 HTML / CSS
HTML5 Canvas实现360度全景图的示例代码
2018/01/29 HTML / CSS
英国时尚泳装品牌:Maru Swimwear
2019/10/06 全球购物
销售助理岗位职责
2014/02/21 职场文书
乡镇交通安全实施方案
2014/03/29 职场文书
优秀共产党员先进事迹材料
2014/05/06 职场文书
员工自我工作评价
2015/03/06 职场文书
python 中[0]*2与0*2的区别说明
2021/05/10 Python
dubbo服务整合zipkin详解
2021/07/26 Java/Android