JS调用栈:为何会栈溢出
JS调用栈:为何会栈溢出
- JS调用栈
- 什么是函数调用
- 什么是栈
- 在开发中利用调用栈
- 栈溢出
JS调用栈
JavaScript 经常会出现一个函数中调用另外一个函数的情况,调用栈就是用来管理函数调用关系的一种数据结构,首先你要先弄明白函数调用和栈结构
什么是函数调用
先来看一段简单的示例代码:
var a = 2
function add() {var b = 10return a + b
}
add()
下面利用这段简单的示例代码来解释下函数调用的过程(参考下图):
- 在执行函数
add()
之前,JavaScript 引擎会为上面这段代码创建全局执行上下文,代码中全局变量和函数都保存在这个全局上下文的变量环境中 - 执行上下文准备好之后,便开始执行全局代码,当执行到
add()
时,JavaScript 判断这是一个函数调用,那么将会从全局执行上下文中取出add
函数代码 - 接下来对取出的
add
函数代码进行编译,并创建该函数的执行上下文和可执行代码 - 最后执行代码,输出结果
流程可以参考下图:
如果你不知道为何变量环境中的
a = undefined
,建议你先去了解JS变量和函数提升
也就是说在执行 JavaScript 时,可能会存在多个执行上下文,那么 JavaScript 引擎是如何管理这些执行上下文的呢?
答案就是通过一种叫栈的数据结构。
什么是栈
栈就类似于一端被堵住的单行线,栈中的元素满足后进先出的特点。JavaScript 引擎正是利用栈的这种结构来管理执行上下文的,在执行上下文创建好后,JavaScript 引擎会将其压入栈中,通常这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈(call stack
)。
为了更好的理解调用栈,下面来看一段稍微复杂点的示例代码:
var a = 2
function add(b, c) {return b + c
}
function addAll(b, c) {var d = 10result = add(b, c)return a + result + d
}
addAll(3, 6)
- 第一步,创建全局上下文,并将其压入栈底。变量
a
、函数add
和addAll
都保存在了全局上下文的变量环境对象中 - 此时已经没有声明变量和函数了,开始执行可执行代码,首先会执行
a = 2
的赋值操作 - 继续执行,调用
addAll()
函数。JavaScript 引起会编译该函数,并为其创建一个函数执行上下文,并将其压入栈中 addAll
的执行变量中先定义d = undefined
,然后执行可执行代码时会执行add()
函数- 为
add
函数创建函数上下文,并将其压入栈中 - 当
add
函数返回时,该函数的执行上下文就会从栈顶弹出,并将result
值设置为add()
执行的返回值 - 紧接着
addAll()
执行最后一个操作后返回,addAll
的执行上下文也会从栈顶弹出,此时调用栈就只剩下全局上下文了 - 至此,整个 JavaScript 流程执行结束
流程图可参考下图:
调用栈是 JavaScript 引擎追踪函数执行的一个机制,当一次有多个函数被调用时,通过调用栈能够追踪到哪个函数正在被执行以及函数之间的调用关系。
在开发中利用调用栈
当我们在 add
函数返回值之前打入一个断点
function add(b, c) {debuggerreturn b + c
}
刷新页面,打开浏览器开发者中的 Source
面板
图中,Call Stack
下面显示出来的就是函数的调用栈,栈底部是 anonymous
,也就是全局的函数入口,中间的是 addAll
函数,顶部是 add
函数,跟我们上面分析的执行流程图一样,这就清晰地反映了函数的调用关系。
除此以外,还可以使用 console.trace()
来输出当前的函数调用关系,比如将上面的 debugger
替换成 console.trace()
,控制台打印结果如下:
栈溢出
调用栈是有大小的,当入栈的执行上下文超过一定数目,JavaScript 引擎就会报错,我们将这种错误叫做栈溢出。特别是在写递归的时候,很容易出现这种错误。比如下面的这段代码:
function division(a, b) {return division(a, b)
}
console.log(division(1, 2))
JavaScript 引擎调用函数 division
时创建函数执行上下文,压入栈中;执行 division
函数内部可执行代码时又遇到了 division
函数,所以它会再创建一个函数执行上下文,因为这个函数是递归且没有任何终止条件的,所以会一直反复创建函数执行上下文并压入栈中,但栈是有容量限制的,超过最大数量后就会出现栈溢出的错误。
相关文章:

JS调用栈:为何会栈溢出
JS调用栈:为何会栈溢出 JS调用栈什么是函数调用什么是栈在开发中利用调用栈栈溢出 JS调用栈 JavaScript 经常会出现一个函数中调用另外一个函数的情况,调用栈就是用来管理函数调用关系的一种数据结构,首先你要先弄明白函数调用和栈结构 什么…...
代码随想Day52 | 300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
300.最长递增子序列 这道题目的重点在于动态数组的定义 dp[i]:以nums[i]为结尾的最长递增子序列,因为这样定义可以进行递推; 递推:j从0-i进行对比,如果nums[i]大于nums[j],dp[i]dp[j]1; 初始化…...

使用 pytest 相关特性重构 appium_helloworld
一、前置说明 在 pytest 基础讲解 章节,介绍了 pytest 的特性和基本用法,现在我们可以使用 pytest 的一些机制,来重构 appium_helloworld 。 appium_helloworld 链接: 编写第一个APP自动化脚本 appium_helloworld ,将脚本跑起来 代码目录结构: pytest.ini 设置: [pyt…...

猪目标检测数据集VOC格式600张
猪是一种常见的哺乳动物,通常被人们认为是肉食动物,但实际上猪是杂食性动物,以植物性食物为主,也有偶尔食肉的习性。猪的体型较大,圆胖的体型和圆润的脸庞使其显得憨态可掬。它们主要通过嗅觉来感知周围环境࿰…...

Pandas中concat的用法
Pandas中concat的用法 pd.concat 是 pandas 库中的一个函数,用于将多个 pandas 对象(如 Series、DataFrame)沿指定轴进行合并连接。 pd.concat(objs, axis0, joinouter, ignore_indexFalse, keysNone, levelsNone, namesNone, verify_in…...

【C++】引用详解
前言 在学习C语言时,我们通常会遇到两个数交换的问题,为了实现这一功能,我们会编写一个经典的Swap函数,如下所示: void Swap(int *a, int *b) {int tmp *a;*a *b;*b tmp; } 然而,这个Swap函数看起来可…...
平时的一些思考内容
文章目录 阶乘位运算求概率 阶乘 阶乘是一很迷人的,刚开始的的变化还不是很大,到后面变化类似于直线上升的,不知道现实中哪些实例来表示阶乘。19的阶乘就已经超过了long了,在竞赛或者其他中要求2023或者很大数字的阶乘就需要考虑…...

AIGC时代下,结合ChatGPT谈谈儿童教育
引言 都2024年了,谈到儿童教育,各位有什么新奇的想法嘛 我觉得第一要务,要注重习惯养成,我觉得聊习惯养成这件事情范围有点太大了,我想把习惯归纳于底层逻辑,我们大家都知道,在中国式教育下&a…...
Java中的锁(一)
一、前言 在Java中,锁是用于多线程同步的重要概念。它可以保护共享资源,确保多个线程在访问共享资源时的数据一致性。 共享资源指的是多个线程同时对同一份资源进行访问 (读写操作),被多个线程访问的资源就称为共享资源。 如何保证多个线程访…...

CSS-SVG-环形进度条
线上代码地址 <div class"circular-progress-bar"><svg><circle class"circle-bg" /><circle class"circle-progress" style"stroke-dasharray: calc(2 * 3.1415 * var(--r) * (var(--percent) / 100)), 1000" …...

英语中修饰头发的形容词顺序是怎么样的(加补充)
一、英语描述发型 :漂亮长短形状颜色头发。 例如她有一头美丽的黑色的直发。She has beautiful long straight black hair.二、多个形容词修饰同一名词时的顺序是固定的,其顺序为:①冠词、指示代词、不定代词、物主代词②序数词基数词③一般性描绘形容词…...
python的WebSocket编程详解,案例群聊系统实现
1.websocket相关 1.1为什么要用websocket 如果有需求要实现服务端向客户端主动推送消息时(比如聊天室,群聊室)有哪几种方案 轮训:让浏览器每隔两秒发送一次请求,缺点:有延时,请求太多网站压力…...
flutter学习-day22-使用GestureDetector识别手势事件
文章目录 1. 介绍2. 使用2-1. 单击双击和长按2-2. 拖动和滑动2-3. 缩放 3. 注意点 1. 介绍 在 flutter 中,GestureDetector 是手势识别的组件,可以识别点击、双击、长按、拖动、缩放等手势事件,并且可以与子组件进行交互,构造函数…...

uni-app tabbar组件
锋哥原创的uni-app视频教程: 2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中...共计23条视频,包括:第1讲 uni…...

【Midjourney】Midjourney根据prompt提示词生成人物图片
目录 🍇🍇Midjourney是什么? 🍉🍉Midjourney怎么用? 🔔🔔Midjourney提示词格式 Midjourney生成任务示例 例1——航空客舱与乘客 prompt prompt翻译 生成效果 大图展示 细节大…...

Oracle 拼接字符串
语法 使用||拼接如果内容中有单引号,则可在该单引号前面再加一个单引号进行转义 例子 比如有一个业务是根据需要生成多条插入语句 select insert into des_account_des_role(des_account_id, roles_id) values( || id || , || (select id from des_role where wo…...
探究公有云中的巨人:深入分析大数据产品的架构设计
目录 一、服务器分类 二、公有云基础和产品 网络 vpc专有网络 弹性公网IP(Elastic IP)...

亚马逊云科技 re:Invent 2023 产品体验:亚马逊云科技产品应用实践 王炸产品 Amazon Q,你的 AI 助手
意料之中 2023年9月25日,亚马逊宣布与 Anthropic 正式展开战略合作,结合双方在更安全的生成式 AI 领域的先进技术和专业知识,加速 Anthropic 未来基础模型的开发,并将其广泛提供给亚马逊云科技的客户使用。 亚马逊云科技开发者社…...

并发编程大杀器,京东多线程编排工具asyncTool
一、简介 并发编程大杀器,京东多线程编排工具asyncTool,可以解决任意的多线程并行、串行、阻塞、依赖、回调的并行框架,可以任意组合各线程的执行顺序,带全链路执行结果回调。多线程编排一站式解决方案。 二、特点 多线程编排&am…...

【开源项目】智慧交通~超经典开源项目实景三维数字孪生高速
数字孪生高速运营管理平台,以提升高速公路管理水平和方便出行为主要目标,充分利用云计算、AI、大数据等,实现对高速公路控制、指挥、运营的智能化。飞渡科技以实景三维数据为基础,基于大数据、高分遥感、数据分析以及数据融合等前…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...