Skip to content

Latest commit

 

History

History
75 lines (61 loc) · 3.84 KB

08 调用栈.md

File metadata and controls

75 lines (61 loc) · 3.84 KB

08 | 调用栈:为什么JavaScript代码会出现栈溢出?

当一段代码被执行时,JavaScript 引擎先会对其进行编译,并创建执行上下文。 一般说来,有这么三种情况下代码才算是“一段”代码:

  1. 当 JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文, 而且在整个页面的生存周期内,全局执行上下文只有一份。
  2. 当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文, 一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
  3. 当使用 eval 函数的时候,eval 的代码也会被编译,并创建执行上下文。

什么是函数调用

函数调用就是运行一个函数

var a = 2
function add(){
  var b = 10
  return  a+b
}
add()

在执行到函数 add() 之前,JavaScript 引擎会为上面这段代码创建全局执行上下文,包含了声明的函数和变量. 08 调用栈-2023-09-17-14-48-14

首先,从全局执行上下文中,取出 add 函数代码。其次,对 add 函数的这段代码进行编译,并创建该函数的执行上下文和可执行代码。最后,执行代码,输出结果。

就这样,当执行到 add 函数的时候,我们就有了两个执行上下文了——全局执行上下文和 add 函数的执行上下文。

JavaScript 引擎通过一种叫栈的数据结构来管理这些执行上下文。

什么是调用栈

调用栈就是用来管理函数调用关系的一种数据结构。

  • 每调用一个函数,JavaScript 引擎会为其创建执行上下文,并把该执行上下文压入调用栈,然后 JavaScript 引擎开始执行函数代码。
  • 如果在一个函数 A 中调用了另外一个函数 B,那么 JavaScript 引擎会为 B 函数创建执行上下文,并将 B 函数的执行上下文压入栈顶。
  • 当前函数执行完毕后,JavaScript 引擎会将该函数的执行上下文弹出栈。当分配的调用栈空间被占满时,会引发“堆栈溢出”问题。

08 栈溢出__2022-06-26-23-20-42

调用栈有两个指标,最大栈容量和最大调用深度,满足其中任意一个就会栈溢出

chrome浏览器测试栈

function add(n){
    console.log(`第 ${n} 层`)
    return add(n+1)
}
add(1)

08 栈溢出__2022-06-26-23-25-18

什么是 JavaScript 的调用栈

var a = 2
function add(b,c){
  return b+c
}
function addAll(b,c){
  var d = 10
  result = add(b,c)
  return  a+result+d
}
addAll(3,6)

第一步,创建全局上下文,并将其压入栈底。 08 调用栈-2023-09-17-14-52-58

第二步,是调用 addAll 函数。当调用该函数时,JavaScript 引擎会编译该函数,并为其创建一个执行上下文,最后还将该函数的执行上下文压入栈中 08 调用栈-2023-09-17-14-53-09

第三步,当执行到 add 函数调用语句时,同样会为其创建执行上下文,并将其压入调用栈 08 调用栈-2023-09-17-14-51-13

当 add 函数返回时,该函数的执行上下文就会从栈顶弹出,并将 result 的值设置为 add 函数的返回值 08 调用栈-2023-09-17-14-53-32 紧接着 addAll 执行最后一个相加操作后并返回,addAll 的执行上下文也会从栈顶部弹出 08 调用栈-2023-09-17-14-53-48 至此,整个 JavaScript 流程执行结束了。