举个例子
let a = 20;const b = 30;var c;function multiply(e, f) {var g = 20;return e * f * g;}c = multiply(20, 30);
执行上下文如下:
GlobalExectionContext = {ThisBinding: <Global Object>,LexicalEnvironment: {// 词法环境EnvironmentRecord: {Type: "Object",// 标识符绑定在这里a: < uninitialized >,b: < uninitialized >,multiply: < func >}outer: <null>},VariableEnvironment: {// 变量环境EnvironmentRecord: {Type: "Object",// 标识符绑定在这里c: undefined,}outer: <null>}}FunctionExectionContext = {ThisBinding: <Global Object>,LexicalEnvironment: {EnvironmentRecord: {Type: "Declarative",// 标识符绑定在这里Arguments: {0: 20, 1: 30, length: 2},},outer: <GlobalLexicalEnvironment>},VariableEnvironment: {EnvironmentRecord: {Type: "Declarative",// 标识符绑定在这里g: undefined},outer: <GlobalLexicalEnvironment>}}
留意上面的代码,let和const定义的变量a和b在创建阶段没有被赋值,但var声明的变量从在创建阶段被赋值为undefined
这是因为,创建阶段,会在代码中扫描变量和函数声明,然后将函数声明存储在环境中
但变量会被初始化为undefined(var声明的情况下)和保持uninitialized(未初始化状态)(使用let和const声明的情况下)
这就是变量提升的实际原因
执行阶段在这阶段,执行变量赋值、代码执行
如果 Javascript 引擎在源代码中声明的实际位置找不到变量的值,那么将为其分配 undefined 值
回收阶段执行上下文出栈等待虚拟机回收执行上下文
执行栈执行栈,也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文
文章插图
当Javascript引擎开始执行你第一行脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中
每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中
引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文
举个例子:
let a = 'Hello World!';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');
转化成图的形式文章插图
简单分析一下流程:
- 创建全局上下文请压入执行栈
- first函数被调用,创建函数执行上下文并压入栈
- 执行first函数过程遇到second函数,再创建一个函数执行上下文并压入栈
- second函数执行完毕,对应的函数执行上下文被推出执行栈,执行下一个执行上下文first函数
- first函数执行完毕,对应的函数执行上下文也被推出栈中,然后执行全局上下文
- 所有代码执行完毕,全局上下文也会被推出栈中,程序结束
推荐阅读
- 在Java中使用Redis的方法
- MyBatis 超强大的动态 SQL 语句大全
- 推荐一款支持自建服务器的免费国产远控神器:RdViewer Pro
- Shell 脚本中经典的13个面试题
- 一文读懂 Android 系统的源代码
- 一堆令人惊艳的软件工具
- 原生javascript解锁恶心的CSDN强制关注才能阅读让文章自动展开
- 哪些后端框架对 Web 应用程序开发产生了巨大的影响?
- Python接入不同类型数据库的通用接口方法
- 个人没有新闻源报道自己怎么创建? 个人的百度百科怎么弄