一篇文章弄懂javascript中的执行栈与执行上下文


Posted in Javascript onAugust 09, 2019

前言

作为一个前端开发人员,弄清楚JavaScript的执行上下文有助于我们理解js中一些晦涩的概念,比如闭包,作用域,变量提升等等。

执行栈

执行栈用于存储代码执行期间创建的所有执行上下文。具有FILO接口,也被称为调用栈。
当JavaScript代码被运行的时候,会创建一个全局上下文,并push到当前执行栈。之后当发生函数调用的时候,引擎会为函数创建一个函数执行上下文并push到栈顶。引擎会先执行调用栈顶部的函数,当函数执行完成后,当前函数的执行上下文会被移除当前执行栈。并移动到下一个上下文。

let a = 'Hello'

function first() {
  console.log('Inside first function')
  second()
  console.log('Again inside first function')
}

function second() {
  console.log('Inside second function')
}

first()

console.log('Inside Global execution context')

一篇文章弄懂javascript中的执行栈与执行上下文

执行上下文

我们可以理解为执行上下文是js代码被解析和执行时所在环境的抽象概念。
JavaScript的执行上下文分为三种类型:

  • 全局执行上下文:最基本的上下文,只有一个。创建了一个全局对象(eg:浏览器中的window),将this指向全局对象。
  • 函数执行上下文:每次调用函数都会创建一个函数上下文。函数上下文可以存在无数个。
  • Eval函数执行上下文:运行在eval函数中的代码会有一个自己的执行上下文(本文不讨论)。

执行上下文的创建

创建执行上下文又可以分为两个阶段: 1. 创建阶段 2. 执行阶段

创建阶段

在创建阶段,JavaScript引擎会创建LexicalEnvironment(词法环境)组件,VariableEnvironment(变量环境)组件以及this绑定(在全局上下文中,this指向全局对象。在函数执行上下文中,this取决与函数在哪里被调用。)

Lexical  Environment(词法环境)

ES2015规范对词法环境的描述

我们可以理解为词法环境是一种包含标识符(变量/函数的名称)和变量(实际对象:函数/原始值/数组对象等)映射的数据结构。

每个词法环境由两部分组成:Environment Record环境记录(存储变量和函数声明的实际位置)和对外部环境的引用(可以访问其外部词法环境)

环境记录分为两种:

  • Declarative environment record(声明性环境记录): 存储变量和函数声明。
  • Object environment record(对象环境记录):全局词法环境。除了变量和函数声明外,对象环境记录还存储全局绑定对象。

tips:对于函数执行上下文来说,环境记录还包含了一个arguments对象,包含了传递给函数的索引和参数之间的映射以及函数参数的数量。

例如:

function foo(a, b) {
  var c = a + b
}

// argument object
Arguments: {0: 2, 1: 3, length: 2}

VariableEnvironment(变量环境)

变量环境也是一个词汇环境,因此它具有上面定义的词法环境的所有属性和组件。在ES6中,LexicalEnvironment组件和VariableEnvironment组件之间的一个区别是前者用于存储函数声明和变量let和const绑定,而后者仅用于存储变量var绑定。

执行阶段

在执行阶段,会完成对所有变量的分配,代码也会被最终执行。执行上下文的代码会被分成两个阶段:

  1. 进入执行上下文
  2. 代码执行
let a = 20
const b = 30
var c

function multiply(e, f) {
  var g = 20
  return e * f * g
}

c = multiply(20, 30)

当上面的代码被执行的时候,JavaScript引擎会创建一个全局上下文来执行全局代码。

此时的全局上下文:

GlobalExectionContext = {  // 全局上下文
  LexicalEnvironment: {  // 词法环境
    EnvironmentRecord: {  // 环境记录
      type: 'Object', // 类型
      // 标识符
      a: <uninitialized>,
      b: <uninitialized>,
      multiply: <func>
    },
    outer: <null>, // 对外部环境引用
  },
  VariableEnvironment: { // 变量环境
    EnvironmentRecord: {  // 环境记录
      type: 'Object',
      c: undefined
    },
    outer: <null>, // 对外部环境引用
  },
  ThisBinding: <Global Object>  // this绑定
}

在执行阶段,变量会被赋值,此时的全局上下文变成:

GlobalExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      type: 'Object',
      a: 20,
      b: 30,
      multiply: <func>
    },
    outer: <null>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      type: 'Object',
      c: undefined
    }
    outer: <null>
  },
  ThisBinding: <Global Object>
}

当JavaScript引擎遇到函数multiply(20, 30)的时候,会创建一个新的函数上下文:

FunctionExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      type: 'Declarative',
      arguments: {
        0: 20,
        1: 30,
        length: 2
      }
    },
    outer: <GlobalLexicalEnvironment>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
     Type: "Declarative",
     g: undefined
    },
    outer: <GlobalLexicalEnvironment>,
  },
  thisBinding: <Global Object or undefined>
}

之后执行上下文会进入执行阶段, 此时的函数上下文:

FunctionExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      type: 'Declarative',
      arguments: {
        0: 20,
        1: 30,
        length: 2
      }
    },
    outer: <GlobalLexicalEnvironment>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
     Type: "Declarative",
     g: 20
    },
    outer: <GlobalLexicalEnvironment>,
  },
  thisBinding: <Global Object or undefined>
}

当函数执行完毕后。会返回一个值并赋值给变量c,全局上下文被更新。更新完成后,代码执行完毕,程序结束。

参考文章

Understanding Execution Context and Execution Stack in Javascript

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js自动生成对象的属性示例代码
Oct 28 Javascript
jquery选择器需要注意的问题
Nov 26 Javascript
js控住DOM实现发布微博效果
Aug 30 Javascript
详解axios 全攻略之基本介绍与使用(GET 与 POST)
Sep 15 Javascript
Vue2.0 axios前后端登陆拦截器(实例讲解)
Oct 27 Javascript
JavaScript中的一些隐式转换和总结(推荐)
Dec 22 Javascript
vue动态绑定组件子父组件多表单验证功能的实现代码
May 14 Javascript
JS非行间样式获取函数的实例代码
Jun 05 Javascript
11个教程中不常被提及的JavaScript小技巧(推荐)
Apr 17 Javascript
后台使用freeMarker和前端使用vue的方法及遇到的问题
Jun 13 Javascript
微信小程序getLocation 需要在app.json中声明permission字段
Mar 03 Javascript
基于Vue全局组件与局部组件的区别说明
Aug 11 Javascript
vue中组件通信的八种方式(值得收藏!)
Aug 09 #Javascript
Vue全局loading及错误提示的思路与实现
Aug 09 #Javascript
使用Vue CLI创建typescript项目的方法
Aug 09 #Javascript
详解vue beforeRouteEnter 异步获取数据给实例问题
Aug 09 #Javascript
微信小程序如何连接Java后台
Aug 08 #Javascript
vue 实现Web端的定位功能 获取经纬度
Aug 08 #Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
Aug 08 #Javascript
You might like
php使用str_replace实现输入框回车替换br的方法
2014/11/24 PHP
Dwz与thinkphp整合下的数据导出到Excel实例
2014/12/04 PHP
PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码
2016/03/25 PHP
PHP扩展类型及安装方式解析
2020/04/27 PHP
JS不间断向上滚动效果代码
2013/12/25 Javascript
javascript校验价格合法性实例(必须输入2位小数)
2014/05/05 Javascript
JavaScript设置body高度为浏览器高度的方法
2015/02/09 Javascript
jQuery结合AJAX之在页面滚动时从服务器加载数据
2015/06/30 Javascript
JavaScript动态提示输入框输入字数的方法
2015/07/27 Javascript
cocos2dx骨骼动画Armature源码剖析(一)
2015/09/08 Javascript
简单实现的JQuery文本框水印插件
2016/06/14 Javascript
JS实现页面进入和返回定位到具体位置
2016/12/08 Javascript
详谈表单重复提交的三种情况及解决方法
2017/08/16 Javascript
详解VueJS应用中管理用户权限
2018/02/02 Javascript
JS中获取 DOM 元素的绝对位置实例详解
2018/04/23 Javascript
react 创建单例组件的方法
2018/04/26 Javascript
JavaScript基于对象方法实现数组去重及排序操作示例
2018/07/10 Javascript
springboot+vue+对接支付宝接口+二维码扫描支付功能(沙箱环境)
2020/10/15 Javascript
[44:58]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第二场
2018/04/06 DOTA
[54:53]完美世界DOTA2联赛PWL S2 GXR vs PXG 第二场 11.18
2020/11/18 DOTA
Python2.X/Python3.X中urllib库区别讲解
2017/12/19 Python
Python3实现的Mysql数据库操作封装类
2018/06/06 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
解决pip install xxx报错SyntaxError: invalid syntax的问题
2018/11/30 Python
为什么你还不懂得怎么使用Python协程
2019/05/13 Python
Python中最好用的命令行参数解析工具(argparse)
2019/08/23 Python
Django 对IP访问频率进行限制的例子
2019/08/30 Python
python 截取XML中bndbox的坐标中的图像,另存为jpg的实例
2020/03/10 Python
倩碧澳大利亚官网:Clinique澳大利亚
2019/07/22 全球购物
美国波西米亚风格精品店:South Moon Under
2019/10/26 全球购物
大专生自我评价
2014/01/28 职场文书
护士节演讲稿开场白
2014/08/25 职场文书
先进教师事迹材料
2014/12/16 职场文书
写给领导的感谢信
2015/01/22 职场文书
教师廉洁自律个人总结
2015/02/10 职场文书
校本研修个人总结
2015/02/28 职场文书