ES 模块
JavaScript 官方的模块系统:导出/导入、importmap、与普通脚本的五处关键区别。
ES 模块(ESM)
ES 模块是 JavaScript 官方的模块系统 —— 它让一个 JS 文件能导出能力给别的文件用,也能导入别人写好的能力。
1. 导出:让别的文件能用
export const name = "ESM"; // 命名导出export function hello() { return name; }export default function main() {} // 默认导出(一个模块只能有一个)2. 导入:把能力拿过来
import main, { name, hello } from "./export.js";import { hello as hi } from "./export.js"; // 重命名import * as mod from "./export.js"; // 整体导入成对象import("./export.js"); // 动态导入(返回 Promise)3. import map:给「裸模块名」指路
浏览器不认识 import x from "some-lib" 这种裸模块名(它不知道去哪找)。
importmap 就是那张「名字 → URL」的映射表:
<script type="importmap">{ "imports": { "some-lib": "/vendor/some-lib.js" } }</script>这也是 Vite 做依赖预构建的原因之一 —— 它会把裸模块名重写成合法 URL。
4. 与普通脚本的区别
| 特性 | <script> | <script type="module"> |
|---|---|---|
| 作用域 | 全局 | 模块内(有自己的作用域) |
| 严格模式 | 否 | 默认开启 |
顶层 this | window | undefined |
| 执行时机 | 立即 | 延迟(像 defer) |
| 重复引入 | 多次执行 | 只执行一次 |
5. 易错点
· import 声明会被提升 —— 它总在最前面执行,别指望靠位置控制顺序;
· 默认导出 vs 命名导出:默认导出可以随便改名(import x from ...),命名导出必须名字对上;
· 循环导入能工作,但拿到的可能是「还没初始化完」的值 —— 尽量别设计成环;
· 顶层 await 在模块里合法(普通脚本里不合法)。
引用了这个词条的文章
- 新人报到:我为什么开始写博客ES 模块
