这次一定吃透-执行上下文

时间:2021-1-8 作者:admin

什么是执行上下文

执行上下文其实是一个抽象概念,每一行JavaScript代码的执行都是在执行上下文中运行的。

执行上下文的类型

  • 全局执行上下文:最基础的上下文,一段代码的执行都是首先创建全局执行上下文。一段代码只能有一个全局执行上下文

  • 函数执行上下文:在全局执行上下文里面,没调用一个函数,都会创建一个新的上下文,这就是函数执行上下文,函数执行上下文可以有多个,按照创建的顺序执行。

  • eval函数执行上下文:执行eval函数内代码时创建,用不到就不介绍了

执行上下文栈

我们已经知道了,代码执行过程中,会创建多个执行上下文,而这些执行上下文之间又是怎么相处的,怎么执行的呢?这里就用到了执行栈。

栈结构我们都知道,是一种先进后出的数据结构,而执行栈就是用栈结构来存储多个执行上下文,下面来看一下执行栈中的执行上下文是怎么一个个运行的。

创建执行上下文

执行上下文的概念和运行过程我们都了解了,下面就来看看执行上下文到底是怎么创建的。

创建执行上下文主要有两个步骤

  1. 创建阶段

  2. 执行阶段

好像废话一样,我们一句一句的研究一下这些废话

创建阶段

创建阶段可以分为三步:

  1. this绑定:每个执行上下文都有一个this,创建的过程首先来确定这个this,对于全局执行上下文很好说,就是全局对象,对于浏览器来说就是window,而对于函数执行上下文,就比较复杂了,后面会有专门文章来介绍,这里就说一句,谁调用就是谁

  2. 词法环境:词法环境就是标识符到变量/函数的关联映射。这里面还有很多麻烦的东西,在看下去肯定就晕了,这里只在介绍一点,那就是词法环境包含:

    1. 环境记录器:存储变量函数的实际声明位置

    2. 外部环境的引用:访问父作用域(全局执行上下文没有)

  3. 变量环境:变量环境也是一种词法环境,它们之间的不同点在于:词法环境用于存储函数声明和变量绑定(let和const),变量环境用来存储var变量绑定

变量声明提升

这里的不同就是造成变量声明提升的原因,在创建阶段,引擎会找出所有的变量和函数声明,使用var声明的就被声明为undefined,而let和const就显示未初始化。

执行阶段

完成所有的变量分配,最后执行代码。

最后

看段代码,加深执行上下文栈的执行过程

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();
//ECStack.push(<checkscope> functionContext);
//ECStack.push(<f> functionContext);
//ECStack.pop();
//ECStack.pop();
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();
//ECStack.push(<checkscope> functionContext);
//ECStack.pop();
//ECStack.push(<f> functionContext);
//ECStack.pop();

上面代码注释部分就是执行上下文栈的压入弹出步骤,只要记住函数执行的时候就会创建上下文并压入栈中,就很容易理解。但是最终的输出结果都是‘local scope’,为什么会这样呢,这里我们就要清楚每个执行上下文所包含的变量环境,作用域链和this

这里分析上面第一段代码的执行上下文,理解了第二段也不是问题了

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。