深刻浅出javascript (2)—— 调用栈(执行上下文栈)

有了上一篇文章的基础,今天咱们接着来学习 javascript 调用栈。
先来回顾下前面文章的内容:
三种 JavaScript 的可执行代码(executable code):javascript

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

请记住这三种建立执行上下文的状况,接下来咱们来看看调用栈。讲清楚调用栈以前须要先弄明白函数调用和栈结构。java

函数调用

函数调用就是运行一个函数,咱们结合下面的代码说明:segmentfault

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

在执行到函数 add() 以前,JavaScript 引擎会为上面这段代码建立全局执行上下文(全局代码产生执行上下文),包含了声明的函数和变量,你能够参考下图:
image.png闭包

从图中能够看出,代码中全局变量和函数都保存在全局上下文的变量环境中。函数

执行上下文准备好以后,便开始执行全局代码,当执行到 add 这里,JavaScript 判断这是一个函数调用(调用函数产生执行上下文),那么将执行如下操做:学习

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

完整流程参考下图:网站

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

也就是说在执行 JavaScript 时,可能会存在多个执行上下文,那么 JavaScript 引擎是如何管理这些执行上下文的呢?3d

答案就是咱们今天的主题 —— 经过调用栈管理code

JavaScript 的调用栈

JavaScript 引擎利用栈的结构来管理执行上下文。在执行上下文建立好后,JavaScript 引擎会将执行上下文压入栈中,一般把这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈。
下面咱们再来看段稍微复杂点的示例代码:

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

在上面这段代码中,你能够看到它是在 addAll 函数中调用了 add 函数,那在整个代码的执行过程当中,调用栈是怎么变化的呢?

下面咱们就一步步地分析在代码的执行过程当中,调用栈的状态变化状况。

第一步,建立全局上下文,并将其压入栈底。以下图所示:

image.png

从图中咱们能够看出(编译阶段),变量 a、函数 add 和 addAll 都保存到了全局上下文的变量环境对象中。

全局执行上下文压入到调用栈后,JavaScript 引擎开始执行全局代码。首先会执行 a=2 的赋值操做,执行该语句会将全局上下文变量环境中 a 的值设置为 2。设置后的全局上下文的状态以下图所示:

image.png

接下来,第二步是调用 addAll 函数。当调用该函数时,JavaScript 引擎会编译该函数,并为其建立一个执行上下文,最后还将该函数的执行上下文压入栈中,以下图所示:

image.png

addAll 函数的执行上下文建立好以后,便进入了函数代码的执行阶段了,这里先执行的是 d=10 的赋值操做,执行语句会将 addAll 函数执行上下文中的 d 由 undefined 变成了 10。

而后接着往下执行,第三步,当执行到 add 函数调用语句时,一样会为其建立执行上下文,并将其压入调用栈,以下图所示:

image.png

当 add 函数返回时,该函数的执行上下文就会从栈顶弹出,并将 result 的值设置为 add 函数的返回值,也就是 9。以下图所示:

image.png

紧接着 addAll 执行最后一个相加操做后并返回,addAll 的执行上下文也会从栈顶部弹出,此时调用栈中就只剩下全局上下文了。最终以下图所示:

image.png

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

这里强烈推荐一个国外小哥的网站,能够很是清楚的展现调用栈的入栈和出栈过程,还能够有闭包的过程哦(https://tylermcginnis.com/jav...

好了,今天关于 javascript 调用栈的内容就结束了,下一篇文章咱们来说解一下let和const

相关文章
相关标签/搜索