JS学习笔记:什么是执行上下文,执行上下文的创建和执行

115 阅读4分钟

JS执行上下文

执行上下文

  • 执行上下文:是当前代码运行时的上下环境

  • 执行上下文分三种类型

    1. 全局执行上下文:JS 代码一开始运行就存在,而且一个程序只会有一个全局执行上下文,只要不是在函数内执行的都是在全局执行上下文,

      • 全局执行上下文会做两件事

      1. 创建一个面向浏览器的window对象
      2. 会创建一个this 指针,这个this 指向window 对象
    2. 函数执行上下文:函数上下文是函数被调用的时候创建的

    3. Eval 函数执行上下文:执行在 eval 函数内部的代码也会有它属于自己的执行上下文, JavaScript 不经常使用 eval,先不管(懒得看)

    let a = '哈哈哈哈';
    function first() {
      console.log('first11111');
      second();
      console.log('first22222');
    }
    ​
    function second() {
      console.log('second');
    }
    ​
    first();
    console.log('最后');
    

代码执行顺序:

  1. 创建全局执行上下文,并且压入到调用栈中。
  2. 调用first函数,并创建函数执行上下文压入到栈中。
  3. 打印 console.log('first11111');
  4. 调用函数second,创建second 的函数执行上下文并压入调用栈
  5. 打印 console.log('second');
  6. 完成second 的调用函数执行上下文弹出调用栈并销毁,并且控制流会进入到下一个上下文,即first函数的上下文。
  7. 打印console.log('first22222');
  8. first函数执行完成,上下文弹出调用栈并销毁,控制流会到达下一个执行上下问即全局执行上下文。
  9. 打印console.log('最后');
  10. 弹出全局执行上下文。

在创建执行上下文的时候会有三个步骤:

  1. 绑定this

  2. 创建词法环境组件

  3. 创建变量环境组件

    ExecutionContext = {
      // 绑定this
      ThisBinding = <this value>,
      // 创建词法环境
      LexicalEnvironment = { ... },
      // 创建变量环境
      VariableEnvironment = { ... },
    }
    

1. This 的绑定

  • 在创建全局执行上下文的时候,首先会确定this指针的指向,浏览器是window对象
  • 在函数中,this 的指向由调用者决定,调用者是引用类型的对象,那么this指向的就是这个引用对象,否则this 执行全局对象,(普通函数是没有this的,箭头函数才有this)

2. 词法环境组件:

  • 词法环境是一种持有标识符的变量的映射的结构,标识指的是变量名或者函数名,变量即需要映射的引用数据或者原始类型数据
  • 词法环境两部分组成,两种类型

  • 两个部分:环境记录器和外部环境引用

    1. 环境记录器:用来存储变量声明和函数声明的位置(即在什么地方声明的)

      • 环境记录器分为两种:

        1. 在全局词法环境中,环境记录器被称为对象环境记录器,是用来定义存储在全局上下文中变量和函数关系。
        2. 在函数词法环境中,环境记录器被称为声明式环境记录器,是用来存储变量、函数或者参数等,声明式环境记录器中还会包含有用来传递给函数的arguments对象和参数的length
    2. 外部环境引用:用来访问父级的词法环境

  • 两种类型:一种是全局词法环境类型,一种是函数词法环境类型。

    1. 全局词法环境(全局执行上下文),是没有外部环境引用存在的,它本身就拥一些内建的 (Array/Object)引用对象和一些原型函数,还会有一些用户自定义的变量(全局变量),拥有指向全局对象(window)的this。
    2. 函数词法环境(函数执行上下文),是在函数内部定义的变量,记录在环境记录器中,拥有外部环境的引用,引用的外部环境有可能是全局环境也有可能是包裹在外部函数的函数词法环境

3. 变量环境组件:

它其实也是一种词法环境,它的环境记录器拥有变量声明语句在执行上下文中被创建时的绑定关系,所以它同样由环境记录器和外部环境引用组成,在 ES6 中,词法环境组件和变量环境的一个不同就是前者被用来存储函数声明和变量(letconst)绑定,而后者只用来存储 var 变量绑定(其实就是变量提升的存在)

#以上是创建阶段

#执行阶段:

在执行阶段,在代码中声明的位置如果找到 let 变量的值,它会被赋值为 undefined,所以let不是不会定义为undefined,而是在执行阶段才会被定义,而var是在创建阶段被定义为undefined

结束

以上仅为学习笔记本,如有不对还望不吝指正,如对各位朋友有所帮助还请点赞和评论,谢谢~~