wangzhenggui/blog

javaScript深入之执行上下文栈

Opened this issue · 0 comments

执行顺序

我们都知道javascript语言是一门顺序执行的语言,但是有的时候却出现一些与我们预期情况不太一样的结果出现,这是为什么呢?我们通过俩个例子来分析一下...

console.log(up); // undefined  变量提升
var up = '123';

var foo = function () {

    console.log('foo1');

}

foo();  // foo1

var foo = function () {

    console.log('foo2');

}

foo(); // foo2

这个例子可能很好就能理解,但是背后执行的时候发生了什么你知道吗?再来看看下面一个例子

function fun() {
    console.log('fun')
}
fun();    // fun1
function fun() {
    console.log('fun1')
}
fun();    // fun1

运行结果和你想象的有出入吗?

熟悉javascript的朋友们可能都知道javascript代码并不是一行一行的执行的,而是一段一段执行的。每当执行‘一段’代码的时候,都会进行一个准备工作,例如第一段代码中变量提升,第二段代码中的函数提升。
下面我们来了解一下javaScript中如何来划分这‘一段一段’的代码的?JS引擎又会遇到怎样一段代码才会做‘准备工作’呢?

执行上下文栈

javaScript中有几种可执行代码段呢? 全局作用域、函数作用域、eval代码
当js引擎遇到一个函数的时候,就会做‘准备工作’,这里的准备工作就是 ‘执行上下文’
一个JS文件中会有很多的函数,那么js引擎是怎么管理这么多的执行上下文的呢?JS引擎通过栈的数据结果存储这些执行上下文,我们称它为执行上下文栈
下面模拟一段代码,让大家更清晰的知道这个过程

function fun3() {
    console.log('fun3')
}

function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();

执行过程,栈内数据变化


// fun1()
ECStack.push(<fun1> functionContext);

// fun1中竟然调用了fun2,还要创建fun2的执行上下文
ECStack.push(<fun2> functionContext);

// 擦,fun2还调用了fun3!
ECStack.push(<fun3> functionContext);

// fun3执行完毕
ECStack.pop();

// fun2执行完毕
ECStack.pop();

// fun1执行完毕
ECStack.pop();

// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext