🗒️module

<script src="a.js"></script>                <!-- 引入脚本 -->
<script type="module" src="b.js"></script>  <!-- 引入模块 -->
script
module

默认模式

非严格

严格

top-level

global

module

this

window

undefined

执行

同步

异步

import 声明

不可以

可以

动态 import()

可以

可以

ES6 模块标准有两部分:

  • 声明性语法:用于导入和导出(导入是导出实体的只读视图)

  • 可编程的 loader API:配置加载方式、有条件地加载

模块是单例的,即使一个模块被多次导入,它也只存在一个“实例”。

  1. ES5 模块系统

    • CommonJS 模块:专为同步加载和服务器而设计,偏好单个导出、支持循环依赖

    • 异步模块定义(AMD,如 RequireJS):专为异步加载和浏览器而设计

  2. ES6 Module

    • 语法比 CommonJS 的更紧凑

    • 可以进行静态分析(用于静态检查、优化等)

    • 对循环依赖的支持比 CommonJS 的要好(虽然支持,但尽量避免如此)

1. export 声明

export 不受 temporal dead zone 规则的约束。

两种类型:

  • named export:一个 module 可以有多个(多个命名导出,它们以名称区分)

  • default export:每个 module 只能有一个(单个默认导出,通常是一个 function 或 class)

可以同时使用两者,但通常最好分开使用。

named export

default export

表示在 import 时可以随便起名字。

注意:此时导出的是变量的“值”(和导出变量的行为是不一样的),此时修改变量不会导致其它模块中引入的 default 值发生改变。

re-export 或聚合

2. import 声明

两种方式:

  • import declaration:只能用于 modules 中,且只能在 top-level(不能在 block 或 function 里)

  • dynamic import import():可用于 non-module contexts

import 声明的四种形式:

  1. named import

  2. default import

  3. namespace import

  4. side effect import

静态 import 声明用来导入 read-only live bindings(只读实时绑定),之所以叫 live bindings,是因为它们的值只能由 export 绑定的模块来更新,而 import 它的模块不能 re-assign。

尽管如此,任何持有导出对象的模块都可以改变该对象,并且所有其它导入相同值的模块都可以观察到修改后的值。还可以通过 module namespace object 来观察新值。

需要注意的是,import 与一般的赋值不同,import 后的变量只是改变了名字,它仍然与原来的变量是同一个,即便变量是非引用型的基本类型。

Last updated