执行上下文

概述

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 条评论
登录 后参与评论

相关文章

  • 执行上下文

    解析: a)先填充参数,x:undefined;y:undefined;z:undefined; b)函数申明,在vo对象里有了function fn(){};...

    天天_哥
  • JavaScript-执行上下文

    (1)在JavaScript解释器内部,每次调用执行上下文,分为两个阶段,①创建阶段 和 ②激活/代码执行阶段。

    WEBING
  • JS 执行上下文

    运行JavaScript代码时,当代码执行进入一个环境时,就会为该环境创建一个执行上下文,它会在你运行代码前做一些准备工作,如确定作用域,创建局部变量对象等。

    grain先森
  • ES 基础 —— 执行上下文

    Execution Context(执行上下文)是 ECMA-262 标准中定义的一个抽象概念,用于同 Executable Code(可执行代码)进行区分。

    疯狂的技术宅
  • 一文看懂 JavaScript 执行上下文

    一段 JavaScript 代码在执行之前需要被 JavaScript 引擎编译,编译完成之后,才会进入执行阶段。

    文渊同学
  • 稳扎稳打JS——执行上下文

    上下文环境的初始化在代码执行前完成 JS有三种作用域:全局作用域、函数作用域、eval作用域(不常用,不做介绍)。 在JS代码执行前,首先会对这三种作用域进行...

    大闲人柴毛毛
  • JS the Hardcore: 执行上下文(Execution Context)

    是的,这样解释也可以,但是不够准确。如果仅仅理解到这个层面,而不把这里面涉及到的「执行上下文」(Execution Context, 下面简称 EC)这个概念弄...

    疯狂的技术宅
  • 深入理解JavaScript 执行上下文

    只有理解了执行上下文,才能更好地理解 JavaScript 语言本身,比如变量提升,作用域,闭包等

    木子星兮
  • JS执行上下文与调用栈

    本文分享 了 JavaScript 基础的两个方面:执行上下文和调用堆栈。每当 JavaScript 代码运行时,它都在执行上下文中运行;调用栈则可以在脚本调用...

    前端开发博客
  • 递归执行上下文和堆栈

    执行上下文是一个内部数据结构,它包含关于函数执行的详细信息:控制流现在的位置、当前变量、该变量的值(我们在这里不使用它)和很少的其他内部细节

    公众号---人生代码
  • JS学习系列 05 - 执行上下文

    在我们前面理解了作用域之后,“作用域链”这个概念就产生了。那么作用域链是什么意思,它又是怎么形成的,跟哪些概念有关系,这就是我接下来几章想和大家探讨的内容:执行...

    leocoder
  • 深入理解JavaScript的执行上下文

    执行上下文:指当前执行环境中的变量、函数声明,参数(arguments),作用域链,this等信息。分为全局执行上下文、函数执行上下文,其区别在于全局执行上下文...

    前端老鸟
  • JS执行上下文/作用域/闭包

    2)一般来说内部能访问外部,外部不能访问内部。 那么怎么让外部也能访问内部? —— return

    杨肆月
  • JavaScript中的执行上下文和堆栈[每日前端夜话(0x0C)]

    在这篇文章中,我将深入探讨JavaScript的最基本部分之一,即Execution Context(执行上下文)。 在本文结束时,你应该对解释器了解得更清楚:...

    疯狂的技术宅
  • ECMA-262-3 详解:1、执行上下文

    从来没有深入了解ECMA,网上找了一下,发现早在2010年就有大佬 Dmitry Soshnikov[1] 总结了ECMA中的核心内容,我这里只是翻译记录,加深...

    踏浪
  • 深入理解执行上下文和执行栈

    执行上下文、执行栈、作用域链、闭包,这其实是一整套相关的东西,之前转载的文章也有讲到这些。下面两篇文章会更加详细地解释这些概念。

    Chor
  • 「查缺补漏」JavaScript执行上下文-执行栈

    突然觉得对于一名JavaScript开发者而言,需要知道JavaScript程序内部是如何运行的,那么对于此章节执行上下文和执行栈的理解很重要,对理解其他Jav...

    前端老王
  • 高能预警:执行上下文及执行栈

    打个比方:比如你尿急,是不是得上厕所。尿急是一个动作,就相当于我们的程序代码,那么厕所是不是一个环境,你总不能随地大小便吧。所以这个环境就是指我们程序执行的环境...

    公众号---人生代码
  • JS执行上下文栈和作用域链

    执行上下文就是当前 JavaScript 代码被解析和执行时所在环境的抽象概念, JavaScript 中运行任何的代码都是在执行上下文中运行。

    半指温柔乐

扫码关注云+社区

领取腾讯云代金券