读书笔记|JavaScript中的调用栈:全局执行上下文和函数执行上下文
迪丽瓦拉
2025-05-30 22:25:08
0

前言

原文来自于:浏览器工作原理与实践:08 | 调用栈:为什么JavaScript代码会出现栈溢出?

本文属于个人读书笔记总结,好记性不如烂笔头,学到的东西通过自己的总结后记录下来的才算是自己的知识。

上一篇:读书笔记|JavaScript中的变量提升、编译阶段和执行阶段

正文

一、三种执行上下文

当一段JS代码被执行时,JavaScript引擎会先对其进行编译,并创建执行上下文。

JS中有三种执行上下文:

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

二、函数调用过程中的执行上下文

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

编译阶段,会生成全局执行上下文

执行阶段,当执行到add()时,这是一个函数调用,将会执行以下操作:

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

这样,当执行到add函数时,就有两个执行上下文(全局和函数),JavaScript如何管理多个执行上下文呢?

答案是通过一种叫栈的数据结构来管理!

三、JavaScript调用栈

接下来通过一段稍微复杂的代码来了解JavaScript调用栈。

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函数声明都被放到全局执行上下文,然后执行代码

var a = 2;    //给a赋值
addAll(3,6);  //调用addAll函数

执行之后的全局执行上下文

第二步,调用addAll函数

将addAll函数体从全局执行上下文取出,编译该函数,为其创建一个函数执行上下文,最后将其压入栈中

执行函数体内的执行代码:

var d = 10            // 给d赋值
result = add(b,c)     // 调用add函数

第三步,调用add函数

跟第二步一样的,同样创建add函数执行上下文并压入栈中

执行函数体内的执行代码return b+c,此时add函数调用结束,add函数的执行上下文从栈顶弹出,将返回的值b+c=9赋值给result。

紧接着执行addAll中的return a+result+d,返回结果,addAll的执行上下文也从栈顶弹出,此时调用栈就只剩下全局执行上下文了

至此整个JavaScript流程执行结束。

三、总结

  • 每调用一个函数,JavaScript引擎就会为其创建执行上下文,并把该执行上下文压入调用栈中,然后JavaScript引擎开始执行函数代码。
  • 如果在一个函数A中调用了另一个函数B,那么JavaScript引擎会为B函数创建执行上下文,并将B函数的执行上下文压入栈顶。
  • 当前函数执行完毕后,JavaScript引擎就会将该函数的执行上下文弹出栈。

相关内容