JavaScript 模块化语法 import、export 详解
1. 为什么需要模块化?
在 JavaScript 早期,所有代码都是写在一个 全局作用域 中,这样做的问题是:
- 变量污染:所有变量、函数都是全局的,容易互相干扰。
- 文件依赖管理困难:多个 JS 文件之间的依赖关系混乱,难以维护。
- 代码复用困难:无法方便地拆分和复用代码。
为了解决这些问题,模块化 方案应运而生。
2. JavaScript 模块化的发展
2.1 早期的模块化方案
在 ES6 之前,JS 主要依赖以下方案进行模块化:
- IIFE(立即执行函数表达式):用函数封装代码,避免污染全局变量。
- CommonJS(Node.js 使用):
require()
引入模块。module.exports
导出模块。
- AMD(Asynchronous Module Definition):
- 主要用于浏览器端,使用
define()
和require()
加载模块(如 RequireJS)。
- 主要用于浏览器端,使用
- UMD(Universal Module Definition):
- 兼容 CommonJS 和 AMD,用于同时支持浏览器和 Node.js。
但这些方案都有一定的缺陷,比如 CommonJS 是同步加载的,不适用于浏览器端,AMD 又显得过于复杂。
3. ES6 模块化(ESM)—— import & export
ES6 在 2015 年引入了 import
和 export
关键字,成为 JavaScript 官方的模块化方案(ECMAScript Modules, ESM)。
3.1 基本用法
ES6 模块化使用 export
导出模块,import
导入模块。
(1)导出模块 (export
)
在一个 JavaScript 文件中,我们可以使用 export
关键字导出变量、函数或类。
导出方式 1:命名导出(Named Export)
// math.js export const PI = 3.14159; export function add(a, b) { return a + b; } export class Calculator { multiply(a, b) { return a * b; } }
导出方式 2:默认导出(Default Export)
// greet.js export default function greet(name) { return `Hello, ${name}!`; }
(2)导入模块 (import
)
导入方式 1:导入命名导出
import { PI, add, Calculator } from './math.js'; console.log(PI); // 3.14159 console.log(add(2, 3)); // 5 const calc = new Calculator(); console.log(calc.multiply(2, 3)); // 6
导入方式 2:导入默认导出
import greet from './greet.js'; console.log(greet('Alice')); // Hello, Alice!
导入方式 3:重命名导入
import { add as sum } from './math.js'; console.log(sum(2, 3)); // 5
导入方式 4:整体导入
import * as MathUtils from './math.js'; console.log(MathUtils.PI); // 3.14159 console.log(MathUtils.add(2, 3)); // 5
4. export 详解
4.1 命名导出(Named Export)
命名导出可以导出多个变量、函数或类:
export const name = 'Alice'; export function greet() { return 'Hello!'; } export class User {}
导入时需要使用 相同的名称:
import { name, greet, User } from './module.js';
4.2 默认导出(Default Export)
默认导出通常用于 导出单个模块,例如:
export default function greet() { return 'Hello!'; }
导入时可以使用 任何名称:
import myGreet from './module.js'; console.log(myGreet()); // Hello!
4.3 默认导出 + 命名导出
export default function main() { console.log('Default function'); } export const version = '1.0'; export function helper() { console.log('Helper function'); }
导入:
import main, { version, helper } from './module.js'; main(); // Default function console.log(version); // 1.0 helper(); // Helper function
5. import 详解
5.1 import 只能在模块顶级使用
import
语句不能放在 条件语句或函数内部,否则会报错:
if (true) { import { add } from './math.js'; // 错误 }
正确用法:
import { add } from './math.js'; if (true) { console.log(add(2, 3)); }
5.2 动态导入 import()
ES2020 引入了 动态导入,适用于 按需加载(懒加载):
if (someCondition) { import('./math.js').then(({ add }) => { console.log(add(2, 3)); }); }
也可以用 async/await
:
async function loadMath() { const math = await import('./math.js'); console.log(math.add(2, 3)); } loadMath();
6. ES6 模块 vs CommonJS
特性 | ES6 模块(ESM) | CommonJS(CJS) |
---|---|---|
关键字 | import / export |
require() / module.exports |
运行方式 | 预解析(静态导入) | 运行时(动态导入) |
是否支持顶层导入 | 是 | 否 |
是否支持异步导入 | import() |
仅同步 |
适用环境 | 浏览器 & Node.js (ESM) | Node.js (CJS) |
默认方式 | 适用于浏览器和前端 | Node.js 默认方式 |
特性ES6 模块(ESM)CommonJS(CJS)关键字import
/ export
require()
/ module.exports
运行方式预解析(静态导入)运行时(动态导入)是否支持顶层导入 是 否是否支持异步导入 import()
仅同步适用环境浏览器 & Node.js (ESM)Node.js (CJS)默认方式适用于浏览器和前端Node.js 默认方式
7. 浏览器中如何使用 import / export
7.1 直接使用 <script type=”module”>
<script type="module"> import { add } from './math.js'; console.log(add(2, 3)); </script>
7.2 通过 Webpack / Vite / Rollup
现代前端工具(如 Webpack)可以 打包 ES6 模块 以支持更旧的浏览器:
npm install webpack
8. 结论
- ES6 模块化 (import / export) 是 JavaScript 官方推荐的模块化方案,解决了 代码复用、作用域管理、依赖管理 等问题。
- 默认导出 (export default) 适用于导出单个对象或函数。
- 命名导出 (export {}) 适用于导出多个变量、函数或类。
- 动态导入 (import()) 可实现 懒加载,适用于按需加载模块。
- ESM 和 CommonJS 不兼容,但 Node.js 也开始支持 ESM(.mjs 文件)。
来源链接:https://www.jb51.net/javascript/338814d7j.htm
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
暂无评论内容