前言
ES Module,即 ES6 引入的 js 模块化规范,简称 ESM
(下文将会使用此简称)。ESM 的设计思想是尽可能的静态化,使得编译时就能确定模块的依赖关系,完成模块加载,效率比运行时加载的 CommonJS 的加载方式要高。
运行机制
JS 引擎在对脚本静态分析时,遇到模块加载命令 import
时,会生成一个只读引用。当脚本真正运行时,再根据这个只读引用,向对应模块中取值。因此 ESM 是动态引用,并且不会缓存相关值。
编译时加载
在 ESM 中,import 命令导入时可以指定加载模块中的某个值,而不用加载整个模块。
1 | import { readFileSync } from "fs"; |
这段代码的实质是从 fs 中加载 readFileSync 这个方法,其他的不会加载。
特性
- 在 html 文件中,使用 script 引入 ESM(ES Module),同时设置
type=module
后,这个模块将会被被标识为顶级模块。 - ESM 自动采用严格模式,不管有没有在模块头部添加
use strict
。
相关命令
ESM 提供了如下两个命令:
- export:用于规定模块的对外接口
- import:用于输入其他模块提供的功能
export
export 为导出命令,存在按需导出与默认导出两种导出方式,两种导出方式可以同时存在。
按需导出
即直接使用 export
命令,一般情况下,export 输出的变量就是变量原有的名字
1 | // 方式一 |
但也可以使用 as
关键字来进行重命名。
1 | const name = "asuka"; |
export 语句输出的接口,与其对应的值是动态绑定关系。即通过该接口,可以实时的访问模块内部对应的值。
默认导出
使用 export default
命令,为模块指定默认导出内容,每个模块只能存在一个 export default
命令。
1 | // 方式一 |
本质上讲,export default
就是导出一个键名为 default
的变量或方法,系统允许你在导入时为其指定任何名字。
这在后续模块的整体加载中可以直观了解到。
import
import 为导入命令,存在按需导入与默认导入两种导出方式。
按需导入
使用 import
命令,加载 export
按需导出的模块。
1 | import { name } from "./user.js"; |
也可以通过 as
关键字重命名引入的接口。
1 | import { name as myName } from "./user.js"; |
import
命令具有提升效果,即会提升到整个模块的头部首先执行。
这种行为的本质是由于,import 是在编译阶段执行的,在代码运行之前。
如下面的写法将不会报错:
1 | getName(); |
默认导入
针对默认导入的数据,直接为其指定名称即可。
1 | import user from "./user.js"; |
整体导入
即使用星号 (*) 将模块内的导出全部加载,并使用 as
指定一个对象,所有输出值(包括全部的按需导出与默认导出)全部加载到这个对象上。
例如现在存在模块 user.js
1 | const name = "asuka"; |
使用 import 整体加载 user.js 模块,并指定为 user
对象:
1 | import * as user from "./user.js"; |
可以得到 user 对象的内容如下,可以看到,默认导出的内容被以 default
的键名被放置到了该对象上:
1 | [Module] { |