JavaScript 模块
模块简介
什么是模块
一个模块(module)就是一个文件.js
。一个脚本就是一个模块。模块可以相互加载,并可以使用特殊的指令 export
和 import
来交换功能,从另一个模块调用一个模块的函数
export
关键字标记了可以从当前模块外部访问的变量和函数import
关键字允许从其他模块导入功能
注意:模块只通过 HTTP(s) 工作,在本地文件则不行
模块与常规脚本的区别
-
始终使用 “use strict”
-
每个模块都有自己的模块级作用域,一个模块中的顶级作用域变量和函数在其他脚本中是不可见的
-
模块代码仅在第一次导入时被解析,如果同一个模块被导入到多个其他位置,那么它的代码仅会在第一次导入时执行,如果需要重用需导出它
-
导出的对象在第一个地方修改时,其他地方也修改了
-
import.meta
对象包含关于当前模块的信息。它的内容取决于其所在的环境。在浏览器环境中,它包含当前脚本的 URL,或者如果它是在 HTML 中的话,则包含当前页面的 URL -
模块中顶级
this
时undefined
浏览器特定功能
与常规脚本相比,拥有 type="module"
标识的脚本有一些特定于浏览器的差异:
-
模块脚本时延迟的
- 下载外部模块脚本
<script type="module" src="...">
不会阻塞 HTML 的处理,它们会与其他资源并行加载。 - 模块脚本会等到 HTML 文档完全准备就绪(即使它们很小并且比 HTML 加载速度更快),然后才会运行。包括非module的script
- 保持脚本的相对顺序:在文档中排在前面的脚本先执行。
- 下载外部模块脚本
-
Async 适用于内联脚本(inline script)
-
外部脚本
- 具有相同
src
的外部脚本仅运行一次 - 如果一个模块脚本是从另一个源获取的,则远程服务器必须提供表示允许获取的 header
Access-Control-Allow-Origin
- 具有相同
-
不允许出现裸模块:在浏览器中,
import
必须给出相对或绝对的 URL 路径。没有任何路径的模块被称为“裸(bare)”模块。在import
中不允许这种模块,如import {sayHi} from 'sayHi';
-
兼容性
nomodule
:旧时的浏览器不理解type="module"
。未知类型的脚本会被忽略。对此,我们可以使用nomodule
特性来提供一个后备
script type="module"