JS的函数调用栈有多深?
译者按: 有时候会遇到 Maximum call stack size exceeded 的问题,本文教你 stack size 的计算方法。
- 原文: The maximum call stack size
- 译者: Fundebug
本文采用意译,版权归原作者所有
如果你写了一个一直调用自身的死循环,那么恭喜你,很快就可以看到报错: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/
- Chrome XSS审计之SVG标签绕过
- Java实现的一个简单计算器,有字符分析功能
- Java中实现判断括号是否有效的方法,实用代码
- Java中使用栈实现一个队列,实用代码
- NDK 的开发流程
- 蜜罐背后的影子系统探秘
- Oracle 免费的数据库--Database 快捷版 11g 安装使用与SOD框架对Oracle的CodeFirst支持
- 如何求最小三元组距离
- 如何将Pastebin上的信息应用于安全分析和威胁情报领域
- Optionsbleed 漏洞泄露 Apache Server 的内存信息
- 对两个有序数组进行合并
- No.016 3Sum Closest
- Java中实现解码字符串的方法,实用代码
- PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 二叉树的所有路径
- JavaScript 字符串中的 pad 方法!
- python随机生成经纬度(用于爬虫参数伪造)
- [Go]GO语言实战-gorm获取insert的自增id 和 struct标签不映射到表字段
- 安装vcs
- Mercari数据集——机器学习&深度学习视角
- 查找重复姓名的sql语句
- nginx如何限制并发连接请求数?
- RTSP协议视频平台EasyNVR证书配置界面上传文件地址自动填写错误怎么处理?
- 开发RTSP/RTMP/GB28181/海康SDK/EHome视频融合平台EasyCVR,使用vue-cli3项目搭建多页面模式的方法
- 互联网视频直播&点播平台RTMP推流组件EasyRTMP在弱网环境下推流稳定吗?会不会有推流失败的问题?
- 安防融合视频云服务EasyCVR集成海康EHome协议实现设备录像回看返回会话ID为-1是什么情况?
- git .gitignore 忽略规则的匹配语法
- vue 初始化高德地图
- js -- 判断数组是否为空?