执行上下文

概述

1. 执行上下文概念

2.执行上下文类型

  • 全局执行上下文
  • 函数执行上下文
  • eval函数

3. 执行上下文的内容

  • 变量对象
  • 活动对象
  • 作用域链
  • 调用者信息

4.执行上下文的生命周期

  • 创建阶段
  • 执行阶段
  • 销毁阶段

执行上下文概念

执行上下文为我们的可执行代码块提供了执行前的必要准备工作,如变量对象的定义、作用域链的扩展、提供调用者的对象引用等信息。

执行上下文的类型

JS中有三种执行上下文类型:

  • 全局执行上下文:默认的最基础的执行上下文,一个程序只会存在一个全局上下文,它在整个JS脚本的生命周期中都会存在于执行堆栈的最底部,不会被栈弹出销毁。全局上下文会生成一个全局对象(浏览器环境中是window),并且将this值绑定到全局对象上
  • 函数执行上下文:每当一个函数被调用,都会创建一个新的函数执行上下文(不管这个函数是不是被重复调用)
  • Eval函数执行上下文:执行在eval函数内部的代码也会有它属于自己的执行上下文。

执行上下文的内容

执行上下文是一个抽象的概念,我们可以将它理解为一个Object,一个执行上下文里包括以下内容:

1. 变量对象

2. 活动对象

3. 作用域链

4. 调用者信息

变量对象


原文:Every execution context has associated with it a variable object. Variables and functions declared in the source text are added as properties of the variable object. For function code, parameters are added as properties of the variable object.


每个执行上下文都与一个变量对象相联系,声明的变量和方法作为属性添加到这个变量对象中。对于函数来说,参数也被添加为这个变量对象的属性。

全局执行环境的变量对象始终存在,而函数局部环境的变量,只会在函数执行的过程中存在。

注意 ! :只有函数声明会被加入到变量对象中,而函数表达式会被忽略

// 函数声明,会被加入变量对象
function a(){}
// b是变量s声明,也会被加入变量对象,
// 但是作为函数表达式_b 不会被加入变量对象
var b = function _b(){}

全局执行上下文和函数执行上下文中的变量对象区别:

  1. 全局上下文中的变量对象就是全局对象,以浏览器环境来说,就是window对象
  2. 函数执行上下文中的变量对象内部定义的属性,是不会被直接访问的,只有当函数被调用时,变量对象(VO)被激活为活动对象(AO)时,才能访问到其中的属性和方法

活动对象(activation 简称AO)

函数进入执行阶段时,原本不能访问的变量对象被激活成为一个活动对象,这样才可以访问到其中的属性。

其实变量对象和活动对象是一个东西,只不过处于不同的状态和阶段

作用域链

作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限,当查找变量时,会先从当前上下文的变量对象中查找,如果没有找到,就从父级执行上下文的变量中查找,一直找到全局上下文的变量对象,即全局对象。这样多个执行上下文的变量对象构成的链表叫做作用域链。

函数的作用域在函数创建时就已经确定了,当函数创建时,会有一个名为[[scope]]的内部属性保存所有父级变量在其中。当函数执行中,会创建一个执行环境,然后通过复制函数的[[scope]]属性中的对象构建起执行环境的作用域链,然后,变量对象VO被激活生成AO并添加到作用域链的前端,完整的作用域链创建完成:

Scope = [AO].concat([[scope]])

当前执行代码块的调用者(this)

执行上下文数据结构模拟

executionContext:{
    [variable object | activation object]:{
        arguments,
        variables: [...],
        funcions: [...]
    },
    scope chain: variable object + all parents scopes
    thisValue: context object
}

执行上下文的生命周期

执行上下文的生命周期

  • 创建阶段
  • 执行阶段
  • 销毁阶段

1.创建阶段

函数执行上下文的创建阶段,发生在函数调用时且在执行函数体内的具体代码之前,在创建阶段,JS引擎会做如下操作:

  • 用当前函数的参数列表(arguments)初始化一个”变量对象“并将当前执行上下文与之关联,函数代码块中声明的变量和函数作为属性添加到这个变量对象上。在这个阶段,会进行变量和函数的初始化声明,变量统一定义为undfined需要等到赋值时才会有确值,而函数会直接定义。
  • 构建作用域链
  • 确定 this 的值

2.执行阶段

执行阶段中,JS代码开始逐条执行,在这个阶段,JS引擎开始对定义的变量赋值、开始顺着作用域链访问变量、如果内部有函数调用就会创建一个新的执行上下文压入执行栈并把控制权交出

3.销毁阶段

一般来讲当函数执行完成后,当前执行上下文会被弹出执行上下文栈并且销毁,控制权被重新交给执行栈上一层的执行上下文。

执行上下文栈

当一个脚本运行起来的时候,可能会调用很多函数并产生很多函数执行上下文,为了管理这些执行上下文,JS引擎就创建了“执行上下文栈”(Excution context stack简称ECS)来管理执行上下文。

执行上下文栈遵循LIFO(后进先出)的特征,代码执行期间创建的所有执行上下文,都会交给执行上下文栈进行管理。

当JS引擎开始解析脚本代码时,会首先创建一个全局执行上下文,压入栈底。

每当引擎发现一处函数调用,就会创建一个新的函数执行上下文压入栈内,并将控制权交给该上下文,待函数执行完成后,即将该执行上下文从栈中弹出销毁,将控制权重新给到栈内上一个执行上下文。

注意:递归可能会造成栈溢出

参考:https://juejin.im/post/5ebced85e51d454dc1467664#heading-1


当我们不再需要外在的认可来证明自己时

才能获得真正的自由

本文分享自微信公众号 - 女程序员的日常(gh_df41d619fb70),作者:凛

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Event Loop(1)

    进程描述了CPU在运行指令及加载和保存上下文所需的时间,放在应用上来说就代表了一个程序。线程是进程中的更小单位,描述了执行一段指令所需的时间。

    用户3258338
  • 温故知新-JS深拷贝

    用户3258338
  • 二分查找与大O表示法

    先思考一个简单的问题,1-100的数字,让你猜出我想好的其中一个数,你每猜一次我会说大了或者小了或者对了。你的猜测过程会是怎样的呢?

    用户3258338
  • (ES5版)深入理解 JavaScript 执行上下文和执行栈

    最近在研究 JavaScript 基础性的东西,但是看到对于执行上下文的解释我发现有两种,一种是执行上下文包含:scope(作用域)、variable obje...

    桃翁
  • 详解JavaScript闭包

      要想完全明白JavaScript的闭包,要先明白js中的一些基础原理,然后我再给出一些例子来讲解闭包。   在执行JavaScript时会创建一个执行环境(...

    lpxxn
  • JavaScript之JS的执行环境和作用域

     一、执行环境是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为,每个执行环境都有一个与之关联的变量对...

    郑小超.
  • C#利用SharpZipLib解压或压缩文件夹实例操作

    跟着阿笨一起玩NET
  • 关于CAS实现单点登录(一)

    单点登录:Single Sign On,简称SSO,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    每天学Java
  • SEO人员: 如何让网站排名保持稳定!

    对于长期从事SEO优化的工作人员来讲,我们经常要面临的一个最大的挑战就是让网站排名保持长期稳定,而在实际操作中,我们经常面临各种问题,比如:

    蝙蝠侠IT
  • Codeforces Round #527 (Div. 3) D2. Great Vova Wall (Version 2) (思维+单调栈)

    题目链接:http://codeforces.com/contest/1092/problem/D2

    Ch_Zaqdt

扫码关注云+社区

领取腾讯云代金券