ES6模块是原生静态系统,import必须顶层以支持编译期分析;命名导出需大括号且名称一致,default导出可重命名;路径须带扩展名或斜杠,裸导入需导入映射。

ES6 模块(import/export)不是语法糖,而是 JavaScript 原生的、静态的模块系统——它在编译时就确定依赖关系,不支持运行时动态加载(除非用 import() 动态导入),也不能像 require() 那样写在 if 里。
为什么 import 必须写在顶层作用域
因为 ES6 模块解析是静态的:引擎需要在代码执行前就分析出所有依赖,以便做树摇(tree-shaking)、循环依赖检测和编译优化。一旦放在函数或条件中,就无法静态分析。
-
import和export语句不能出现在if、for、函数内部,否则直接报错:Identifier 'import' has already been declared或Unexpected token 'import' - 想条件加载?必须用动态导入:
if (needMath) { const { add } = await import('./math.js'); } - Node.js 中需启用
"type": "module"或用.mjs后缀,否则默认按 CommonJS 解析,import会报Cannot use import statement outside a module
export 的三种写法及其差异
导出方式决定导入时能否重命名、是否必须解构、是否支持默认导出合并——选错会导致 undefined 或 Unexpected token 错误。
- 命名导出(named export):可多个,导入时必须用大括号且名称一致
export const PI = 3.14; export function square(x) { return x * x; }import { PI, square } from './math.js'; // ✅
import { pi } from './math.js'; // ❌ 报错:pi is not exported - 默认导出(default export):每个模块最多一个,导入时可自定义名,无需大括号
export default function calculate() { ... }import calc from './calc.js'; // ✅
import { default as calc } from './calc.js'; // ✅ 但冗余 - 混合导出要小心:默认导出 + 命名导出可以共存,但不能
export default写两次,也不能export default const x = 1(语法错误)
import 路径必须带扩展名或斜杠吗
在浏览器中必须显式写后缀(如 .js),Node.js(ESM 模式)也默认要求;省略会报 ERR_MODULE_NOT_FOUND。
立即学习“Java免费学习笔记(深入)”;
- 浏览器环境:
import { foo } from './utils.js'✅,import { foo } from './utils'❌(除非服务器配了 MIME 或使用构建工具) - Node.js ESM:
import { bar } from './config.json'❌(JSON 不被原生支持),但import config from './config.json' with { type: 'json' }✅(仅 17.1+) - Vite/Webpack 等工具允许省略扩展名,是因为它们在打包时做了路径解析;但原生 ESM 不行——别把开发环境的便利当成语言特性
模块路径是相对 URL,不是文件系统路径;./ 和 ../ 是必须的,import 'lodash' 这种裸导入只在有导入映射(imports 字段)或包内才合法。实际项目里最容易卡住的,往往不是语法,而是路径解析失败或环境没开 ESM 模式。










