• 【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




  • 相关阅读:
    Java线程volatile(二)
    Java线程synchronized(一)
    Java 平衡二叉树和AVL
    Data striping
    分布式系统的事务处理
    什么是面向对象
    Redis为什么是单线程
    spring 自定义事物同步器(一): TransactionSynchronizationManager 解析
    understand EntityManager.joinTransaction()
    spring 拾遗
  • 原文地址:https://www.cnblogs.com/jiafifteen/p/12201369.html
Copyright © 2020-2023  润新知