ES modules: A cartoon deep-dive

简介: ES modules: A cartoon deep-dive

原文链接

ES模块为JavaScript带来了官方的、标准化的模块系统。然而,它花了一段时间才走到这一步——将近10年的标准化工作。

但等待即将结束。随着火狐60在5月的发布(目前处于beta),所有主流浏览器都将支持ES模块,Node模块工作组目前正在努力将ES模块支持添加到Node.js中。WebAssembly的ES模块集成也在进行中。

许多JavaScript开发人员都知道ES模块一直备受争议。但很少有人真正了解ES模块是如何工作的。

让我们来看看ES模块解决了什么问题,以及它们与其他模块系统中的模块有什么不同。

What problem do modules solve?

仔细想想,用JavaScript编码就是管理变量。它就是给变量赋值,或者给变量加数字,或者把两个变量组合在一起,然后把它们放到另一个变量中。

image.png

因为你的很多代码都是关于改变变量的,你如何组织这些变量将会对你的编码有很大的影响,以及你如何维护这些代码。

一次只考虑几个变量会使事情更容易。JavaScript有一种方法可以帮助您做到这一点,称为作用域。由于JavaScript中作用域的工作方式,函数不能访问在其他函数中定义的变量。

image.png

这是很好的。这意味着当你研究一个函数时,你可以只考虑那个函数。你不必担心其他函数会对你的变量做什么。

不过,它也有一个缺点。这使得在不同函数之间共享变量变得困难。

如果你想在作用域之外共享你的变量该怎么办?处理这个问题的常用方法是将它放在你上面的作用域中,例如全局作用域中。

您可能还记得jQuery时代的这一点。在加载任何jQuery插件之前,必须确保jQuery处于全局作用域中。

image.png    

这是可行的,但是会产生一些烦人的问题。

首先,所有的脚本标记都需要按正确的顺序排列。然后你必须小心确保没有人打乱这个顺序。

如果你打乱了顺序,那么在运行过程中,你的应用程序会抛出一个错误。当函数在它期望的地方(在全局变量上)寻找jQuery而没有找到时,它将抛出一个错误并停止执行。

image.png

这使得维护代码非常棘手。它使删除旧代码或脚本标记变成了一场轮盘赌游戏。你不知道什么东西会坏掉。代码的这些不同部分之间的依赖关系是隐式的。任何函数都可以获取全局函数上的任何东西,因此您不知道哪些函数依赖于哪些脚本。

第二个问题是,因为这些变量位于全局作用域中,所以在全局作用域中的代码的每一部分都可以更改变量。恶意代码可以故意更改该变量,使您的代码做一些您不希望它做的事情,或者非恶意代码可以偶然地破坏您的变量。

How do modules help?

当您使用模块进行开发时,您将建立一个依赖关系图。不同依赖项之间的连接来自您使用的任何导入语句。

通过这些导入语句,浏览器或Node可以准确地知道需要加载哪些代码。您给它一个文件作为图形的入口点。从这里开始,它只跟随任何导入语句来查找其余的代码。

image.png

但是文件本身并不是浏览器可以使用的东西。它需要解析所有这些文件,将它们转换为称为模块记录的数据结构。这样,它就知道文件中发生了什么。

image.png

在此之后,需要将模块记录转换为模块实例。实例结合了两件事:代码和状态。

代码基本上是一组指令。这就像是制作某样东西的食谱。但就其本身而言,您不能使用代码来做任何事情。你需要原材料来配合这些说明使用。

状态是什么?状态给你这些原材料。状态是变量在任何时间点的实际值。当然,这些变量只是内存中保存值的方框的别名。

因此,模块实例将代码(指令列表)与状态(所有变量的值)结合起来。

image.png

我们需要的是每个模块的一个模块实例。模块加载的过程是从这个入口点文件到拥有一个完整的模块实例图。

对于ES模块,这需要三个步骤。

  1. Construction — 查找、下载并将所有文件解析为模块记录。
  2. Instantiation —在内存中找到放置所有导出值的方框(但不要用值填充它们)。然后让导出和导入都指向内存中的这些框。这就是所谓的链接。
  3. Evaluation —运行代码,用变量的实际值填充方框。

image.png

人们说ES模块是异步的。您可以认为它是异步的,因为工作被分为这三个不同的阶段——加载、实例化和评估——并且这些阶段可以分别完成。

这意味着规范引入了一种CommonJS中没有的异步。我将在后面进一步解释,但是在CJS中,一个模块及其下面的依赖项都是一次性加载、实例化和求值的,中间没有任何中断。

然而,这些步骤本身并不一定是异步的。它们可以以同步的方式完成。这取决于是什么在加载。这是因为并非所有的事情都由ES模块规范控制。实际上工作分为两部分,由不同的规范覆盖。

The ES module spec规定了如何将文件解析为模块记录,以及如何实例化和计算该模块。然而,它并没有说明如何首先获得这些文件。

它是获取文件的加载器。装载机在不同的规格中有规定。对于浏览器来说,这个规范就是HTML规范。但是根据所使用的平台,可以使用不同的加载器。

image.png

加载器还精确地控制模块的加载方式。它调用ES模块的方法——ParseModule, Module.Instantiate, and Module.Evaluate。它有点像控制JS引擎字符串的木偶师。

image.png

现在让我们更详细地了解每一步。

目录
相关文章
|
网络协议 ice
STUN, TURN, ICE介绍
STUN STUN协议为终端提供一种方式能够获知自己经过NAT映射后的地址,从而替代位于应用层中的私网地址,达到NAT穿透的目的。STUN协议是典型的Client-Server协议,各种具体应用通过嵌入STUN客户端与STUN Server端通讯来完成交互。
14544 1
|
Java Linux Docker
阿里云云效流水线自动化构建Java项目并发布到docker环境
阿里云云效流水线自动化构建Java项目并发布到docker环境
1407 0
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
DAPO: 面向开源大语言模型的解耦裁剪与动态采样策略优化系统
DAPO(Decoupled Clip and Dynamic Sampling Policy Optimization)是由字节跳动提出的一种突破性的开源大语言模型强化学习系统。基于Qwen2.5-32B基础模型,DAPO在AIME 2024测试中以50分的优异成绩超越了现有最佳模型,
805 6
DAPO: 面向开源大语言模型的解耦裁剪与动态采样策略优化系统
|
SQL Oracle 关系型数据库
国产化人大金仓数据库转库工具:oracle12c数据库转kingbase8.6人大金仓数据库实例演示
国产化人大金仓数据库转库工具:oracle12c数据库转kingbase8.6人大金仓数据库实例演示
1347 0
国产化人大金仓数据库转库工具:oracle12c数据库转kingbase8.6人大金仓数据库实例演示
|
SQL JSON 大数据
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
这篇文章是Elasticsearch的进阶使用指南,涵盖了Search API的两种检索方式、Query DSL的基本语法和多种查询示例,包括全文检索、短语匹配、多字段匹配、复合查询、结果过滤、聚合操作以及Mapping的概念和操作,还讨论了Elasticsearch 7.x和8.x版本中type概念的变更和数据迁移的方法。
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
|
9月前
|
人工智能 自然语言处理 搜索推荐
阿里云携手叫叫,共创儿童学习AI新体验
阿里云携手叫叫,共创儿童学习AI新体验
|
存储 算法 API
Python学习五:函数、参数(必选、可选、可变)、变量、lambda表达式、内置函数总结、案例
这篇文章是关于Python函数、参数、变量、lambda表达式、内置函数的详细总结,包含了基础知识点和相关作业练习。
196 0
|
应用服务中间件 nginx Docker
华为云之SWR容器镜像服务实战
华为云之SWR容器镜像服务实战
1301 1
华为云之SWR容器镜像服务实战
|
JSON Java API
org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe问题探究
org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe问题探究
1875 0