前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >执行上下文

执行上下文

作者头像
用户3258338
发布2020-05-26 16:20:52
9090
发布2020-05-26 16:20:52
举报

概述

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.


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

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

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

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

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

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

活动对象(activation 简称AO)

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

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

作用域链

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

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

代码语言:javascript
复制
Scope = [AO].concat([[scope]])

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

执行上下文数据结构模拟

代码语言:javascript
复制
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


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

才能获得真正的自由

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 女程序员的日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档