【JS核心概念】执行上下文

重点:

  • [x] 理解执行上下文(执行环境)在创建阶段的活动。

一、什么是执行上下文

执行上下文(execution context),可以理解为是当前代码的执行环境

二、执行上下文的类型

1. 在执行JS程序时,每遇到一段可执行代码,都会创建一个执行上下文。JS中的可执行代码分为三种:
  • 全局代码
  • 函数代码
  • eval代码

    2. 每种可执行代码对应一种执行上下文,因此JS中执行上下文也被分为三类:
  • 全局执行上下文
  • 函数执行上下文
  • eval执行上下文(eval不推荐使用,因此后文不再阐述eval执行上下文)

    3. 全局执行上下文
  • 全局执行上下文只有唯一的一个,它与ECMAScript的宿主环境有关,比如在web浏览器中,全局执行上下文表示的是Window对象;
  • 当应用程序退出的时候,比如关闭网页或者浏览器,全局执行上下文才会被销毁

    4. 函数执行上下文
  • 每个函数都有自己的执行上下文,且每被调用一次都会产生一个新的函数执行上下文,即使是调用自身的函数,也是如此;
  • 因此也可以得出:函数执行上下文的个数没有限制。
  • 当函数执行完后,其对应的函数执行上下文就会被销毁。

    5. 执行上下文的特点
  • 单线程:不能同时执行多个;
  • 同步执行:按顺序执行;
  • 全局执行上下文只有一个,在应用程序退出时被销毁;
  • 函数执行上下文的数目没有限制,在函数执行完后被销毁;
  • 每次某个函数被调用时,就会有新的执行上下文产生,即使是调用的自身函数,也是如此。

三、执行上下文栈

1. JS管理执行上下文的方式

一个JS程序会产生多个执行上下文,JS通过栈(先进后出、后进先出)的存取方式来管理执行上下文,我们可以称其为执行栈。

2. 执行栈的工作过程
  • 入栈:程序执行进入一个执行环境时,它的执行上下文就会被创建,并被压入执行栈中,因此全局上下文是第一个入栈的,处于栈底;
  • 执行:处于栈顶的是当前正在执行的上下文;
  • 出栈:当处于栈顶的上下文执行完后,它就会被销毁(全局上下直到应用程序退出才会被销毁),并出栈,控制权交由下一个执行上下文(如果有闭包会阻止该操作,也就是执行上下文不会被销毁)。

四、执行上下文的生命周期

执行上下文是有生命周期的,主要分为两个阶段(对照执行上下文栈)

1、创建阶段
  • 建立作用域链
  • 确定this指向
  • 创建变量对象
    • 变量对象:用于存储执行上下文中定义的变量和函数声明,每个执行上下文都有一个与之关联的变量对象,比如在web浏览器中,全局上下文的变量对象为Window对象;
    • 创建变量对象主要有三个阶段:
      • 变量声明:在当前上下文中每找到一个变量声明,就会在变量对象上添加一个同名属性,该属性只声明不赋值,如果变量对象上已经存在与该属性同名的其他属性,该属性不会对其他同名属性的值产生影响;

        <!-- 变量提升:使用var定义的变量会产生变量提升,原因就在于此 -->
        console.log(a); // undefined
        var a;
        
        console.log(b); // undefined
        var b = 2;
      • 函数声明:每找到一个函数声明,同样也会在变量对象上添加一个以函数名命名的属性,且属性值为该函数的引用,如果变量对象上已经存在与函数名同名的属性,那么它会被覆盖;

        <!-- 函数提升:当变量声明与函数声明同名的时候,函数声明会覆盖变量声明;
        当有多个同名的函数声明时,后面的函数声明会覆盖之前的函数声明。 -->
        foo(); // wuwuwuwu
        function foo() {
            console.log('wuwuwuwu');
        }
        
        <!-- 使用函数字面量的形式创建函数时,此时f为一个普通变量,只是它的值为函数的引用,
        因此在上下文执行阶段会被添加到变量对象上且值为undefined -->
        f(); // TypeError: f is not a function,因此此时f为undefined
        var f = function () {
            console.log('hahaha');
        }
      • 函数的形参:当进入某个函数执行上下文时,如果该函数有形参,则在该函数上下文的变量对象上添加一个与形参同名的属性,且该属性值为实参的值,对于没有传递的参数,其值为undefined。(在函数执行上下文的创建阶段,如果该函数内部有其他变量或函数,同样会进行变量声明、函数声明)
    • 以某个函数的执行上下文为例说明:

      image

      当调用foo(22)时,创建阶段的变量对象为:

      image
2、执行阶段
  • 当创建阶段完成后,就会进入到执行阶段。此时变量对象会转换为活动对象,活动对象上的属性允许被外界访问。
  • 变量对象和活动对象是同一对象,在执行上下文不同生命周期的不同称呼。

image






猜你喜欢

转载自www.cnblogs.com/jiafifteen/p/12201369.html