JavaScript中的执行上下文,既然遇见了这篇图文并茂的文章,干脆看完吧!(系列四)

本文主要是介绍JavaScript中的执行上下文,既然遇见了这篇图文并茂的文章,干脆看完吧!(系列四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JavaScript中的执行上下文

JavaScript基础提升合集

🚀包含this、call、原型链、作用域等基础经典知识点
☕️每周一篇,打好基础,爬升不累
💬最全知识点解析,易懂的代码示例收藏方便阅读
💻完整版在线阅读,猛戳这里~

目录

  • 前言
  • 一、怎么描述执行上下文?
  • 二、执行栈
  • 三、形象化执行栈
  • 四、思考与总结
  • 五、写在最后

前言

在这里插入图片描述
又到了修炼JavaScript内功的时候了,继上一篇《从作用域到作用域链》之后,我们来谈一谈执行上下文,在写这篇文章的时候总感觉无法完整的将知识点串联起来,所以希望大家也能提些建议哦,让这篇文章更值得收藏、点赞哦~

一、怎么描述执行上下文

1.1 本节知识导图:
在这里插入图片描述

1.2 如果描述执行上下文

  1. 当函数执行时,会创建一个称为执行上下文的内部对象。一个执行上下文定义了一个函数执行时的环境;
  2. 当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息 ;
  3. 每个函数在被定义时,就会有一个[[scope]]属性,这个属性里保存着作用域链,而执行的前一刻都会创建一个OA对象,这个对象就是执行上下文,这个OA对象会被插入[[scope]]中作用域链的最顶端,这个对象里保存着函数体声明的所有变量、参数和方法。一个OA对象的有序列表。

上述三条描述都符合执行上下文的一些特点,但侧重点都不一样。

1.3 执行上下文的类型

  1. 全局执行上下文:只有一个,浏览器中的全局对象就是 window 对象,this 指向这个全局对象。

  2. 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文。

  3. Eval 函数执行上下文: 指的是运行在 eval 函数中的代码,很少用而且不建议使用。

在这里插入图片描述

二、执行栈(Execution context stack)

大家都明白,函数的执行顺序和它的定义顺序没关系,但如何解释,就需要从执行栈说起了。

2.1 本节知识导图

在这里插入图片描述

2.2 描述执行栈

执行栈,也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文。

首次运行JS代码时,会创建一个全局执行上下文并Push到当前的执行上下文栈中。每当发生函数调用,引擎都会为该函数创建一个新的函数执行上下文并push到当前执行栈的栈顶。

当栈顶函数运行完成后,其对应的函数执行上下文将会从执行栈中pop出,上下文控制权将移到当前执行栈的下一个执行上下文。

接下来问题来了,我们写的函数多了去了,如何管理创建的那么多执行上下文呢?

三、形象化执行栈

我们利用图片+文字描述的方式来解释这样几段代码:

3.1 为了模拟执行上下文栈的行为,让我们定义执行上下文栈为一个数组:

var ECStack = [];

试想当 JavaScript 开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,ECStack 才会被清空,所以程序结束之前, ECStack 最底部永远有个globalContext

ECStack.push('globalContext');
ECStack // ["globalContext"]

现在 JavaScript 遇到下面的这段代码了:

function fun1() {fun2();
}
function fun2() {fun3();
}
function fun3() {console.log('最后打印3')
}
fun1(); // 最后打印3

当执行一个函数的时候,就会创建一个执行上下文,并且压入(push)执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出(pop)。知道了这样的工作原理,让我们来看看如何处理上面这段代码:

// 伪代码// fun1()
ECStack.push(<fun1> functionContext);// fun1中竟然调用了fun2,还要创建fun2的执行上下文
ECStack.push(<fun2> functionContext);// 擦,fun2还调用了fun3!
ECStack.push(<fun3> functionContext);// fun3执行完毕
ECStack.pop();// fun2执行完毕
ECStack.pop();// fun1执行完毕
ECStack.pop();// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext
注意:除了流程图,在此送大家2020最新企业级 Vue3.0/Js/ES6/TS/React/Node等实战视频教程,点击此处免费获取,小白勿进哦

在这里插入图片描述

再看如下代码:

console.log(1);function father() {console.log(2);(function child() {console.log(3);}());console.log(4);
}
father();console.log(5);
//会依次输出 1 2 3 4 5

分析它的执行栈经历了什么:

在这里插入图片描述
其实到这里我们已经大致了解了执行栈在函数执行前->执行后的流程了,但下一篇文章我们会详细了解释一下,感兴趣的小伙伴不妨点个关注,不跑丢哦~
在这里插入图片描述

四、思考题

现在我们已经了解了执行上下文栈是如何处理执行上下文的,所以让我们看看上篇文章《从作用域到作用域链》最后的问题:

var scope = "global scope";
function checkscope(){var scope = "local scope";function f(){return scope;}return f();
}
checkscope();
var scope = "global scope";
function checkscope(){var scope = "local scope";function f(){return scope;}return f;
}
checkscope()();

两段代码执行的结果一样,但是两段代码究竟有哪些不同呢?

答案就是执行上下文栈的变化不一样。

让我们模拟第一段代码:

ECStack.push(<checkscope> functionContext);
ECStack.push(<f> functionContext);
ECStack.pop();
ECStack.pop();

让我们模拟第二段代码:

ECStack.push(<checkscope> functionContext);
ECStack.pop();
ECStack.push(<f> functionContext);
ECStack.pop();

在这里插入图片描述
如果像上一小结一样画个图的话,两段代码确实很不同哦~

参考

  • 《你不知道的JavaScript》
  • JavaScript深入之执行上下文栈

五、写在最后

JavaScript内功基础部分已经总结到第四篇了,本系列大约会有15篇文章,都是我们在面试最高频的,但工作中常常被忽略的知识点。

热门开源-欢迎star支持

  • 前端进阶
  • 高频经典手撕代码实现
  • 剑指Offer题解
  • LeetCode题解

关于我

  • 花名:余光
  • Writing Vue and JavaScript
  • Working at GaoDing Design
  • A console log tester

如果您看到了最后,不妨收藏、点赞、评论一下吧!!!
持续更新,您的三连就是我最大的动力,虚心接受大佬们的批评和指点,共勉!

这篇关于JavaScript中的执行上下文,既然遇见了这篇图文并茂的文章,干脆看完吧!(系列四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/379732

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav