共享空间网站开发公司,广西地矿建设集团网站,网站建设延期报告,设计师在线网站JS调用栈#xff1a;为何会栈溢出 JS调用栈什么是函数调用什么是栈在开发中利用调用栈栈溢出 JS调用栈
JavaScript 经常会出现一个函数中调用另外一个函数的情况#xff0c;调用栈就是用来管理函数调用关系的一种数据结构#xff0c;首先你要先弄明白函数调用和栈结构
什么… 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 函数所以它会再创建一个函数执行上下文因为这个函数是递归且没有任何终止条件的所以会一直反复创建函数执行上下文并压入栈中但栈是有容量限制的超过最大数量后就会出现栈溢出的错误。