JS执行流程&调用栈
栈和执行上下文
函数调用:
函数调用就是运行一个函数,具体使用方法是使用函数名称跟着一对小括号
var a = 2
function add(){
var b = 10
return a+b
}
add()
在执行到函数add()之前,javascript引擎为为上面的代码创建全局执行上下文,变量环境中包含了声明的函数和变量,参考下图:(具体的可以看上篇文章JS执行流程&变量提升)
代码中的全局变量和函数都保存在全局上下文的变量环境中,然后开始执行全局代码add(),我们知道,这个是属于一个函数调用,因此会执行以下操作:
- 从
全局执行上下文
中,取出add函数
代码 - 对
add函数
的这段代码进行编译
,并创建该函数的执行上下文
和可执行代码
- 执行代码,输出
流程如下
从上面的代码执行流程,我们可以看出,在执行javascript代码的过程中可能会创建多个执行上下文,那么引擎是如何管理
呢?
到这里,我们就要把一种叫栈的数据结构
拿出来使用了,它就用来管理这些执行上下文
栈结构:
什么是栈:
栈的定义:
“栈又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素。”
栈中的元素满足后进先出的特点
什么是javascript调用栈:
前面说到,javascript引擎是通过栈来管理多个执行上下文的,具体过程如下:
- 创建好执行上下文
- javascript引擎将执行上下文压入栈中
通常这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈
了解了调用栈的含义,让我们来看一个例子
var a = 2
function add(a,b){
return b+c
}
function addAll(b,c){
var d = 10
result = add(b,c)
return a + result + d
}
addAll(3,6)
第一步:创建全局上下文,并压入栈底
可以看到,变量a,函数add(),addAll()都保存到了全局上下文变量环境对象中。
全局上下文被压入栈底之后,就开始执行全局代码了,首先var a = 2
先被执行
第二步:接着执行addAll()函数,这是一个函数调用的情况,因此javascript引擎会为其创建一个执行上下文
如下图所示:
addAll()函数执行上下文创建好之后,就开始执行代码吗,先执行的是var d = 10
第三步:接着执行add()函数,这也是一个函数调用的情况,因此javascript引擎会为其创建一个执行上下文
当add()函数返回的时候,函数的执行上下文就会从栈顶弹出,并将result的值设置为add()函数的返回值9
之后addAll执行最后一个相加操作后返回,addAll的执行上下文也从栈顶部弹出
至此,整个javascript流程执行结束