JavaScript 模块化是现代开发中不可或缺的一部分,它让代码更有条理、更易维护、也更便于多人协作。而 export 和 import 是 ES6 提供的标准模块化语法,它们简单易用,但我经常会搞混。今天认真学习了一下,试图彻底掌握 export 和 import。
什么是模块化?为什么需要模块化?
模块化的概念
模块化就是将代码拆分成多个独立的文件(模块),每个模块完成特定的功能,这样代码更易维护和复用。例如,你可以将一个负责计算的代码放在一个文件中,将与界面相关的代码放在另一个文件中。
模块化的好处
- 易维护:将代码拆分后,修改某一部分功能时,不会影响其他部分。
- 可复用:模块可以在多个项目中重复使用,避免重复造轮子。
- 更清晰的代码结构:每个模块只关注自己的职责,代码更易理解。
ES6 模块化语法:export 和 import
在 ES6 中,模块化通过两个核心语法实现:
export:用于导出模块中的变量、函数或类。import:用于引入其他模块的内容。
我们来看具体的用法。
1. 导出:export
export 用于将模块中的内容导出,使它能够被其他模块使用。我们可以通过两种方式导出内容:默认导出和命名导出。
默认导出(export default)
-
特点:
- 每个模块只能有一个默认导出。
- 导入时可以自定义名字,不需要与导出的名字一致。
-
示例:
假设我们有一个文件
math.js,用于导出一个加法函数:// math.js export default function add(a, b) { return a + b; }在另一个文件中,我们可以这样导入它:
// main.js import addFunction from './math.js'; // 可以随意命名 console.log(addFunction(2, 3)); // 输出:5注意:文件中只能有一个
export default,否则会报错。
命名导出(export)
-
特点:
- 一个模块可以有多个命名导出。
- 导入时,名字必须与导出的名字一致(可以通过
as重命名)。
-
示例:
假设我们有一个文件
math.js,导出多个函数:// math.js export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; }在另一个文件中,我们可以这样导入:
// main.js import { add, subtract } from './math.js'; // 必须使用与导出相同的名字 console.log(add(2, 3)); // 输出:5 console.log(subtract(5, 3)); // 输出:2 -
重命名导入:
如果导出的名字太长或与其他变量冲突,可以用as重命名:import { add as addition, subtract as subtraction } from './math.js'; console.log(addition(2, 3)); // 输出:5 console.log(subtraction(5, 3)); // 输出:2
混合使用默认导出和命名导出
你可以在一个模块中同时使用默认导出和命名导出。
-
示例:
文件
math.js:export default function multiply(a, b) { return a * b; } export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; }导入时:
import multiply, { add, subtract } from './math.js'; console.log(multiply(2, 3)); // 输出:6 console.log(add(2, 3)); // 输出:5 console.log(subtract(5, 3));// 输出:2
2. 引入:import
import 用于从其他模块中引入内容。导入的方式与导出的方式密切相关。
引入默认导出
-
语法:
import anyName from './module.js'; -
示例:
假设文件math.js中有一个默认导出:export default function add(a, b) { return a + b; }我们可以这样导入:
import addFunction from './math.js'; // 名字可以自定义 console.log(addFunction(2, 3)); // 输出:5
引入命名导出
-
语法:
import { exportedName } from './module.js'; -
示例:
假设文件math.js中有命名导出:export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; }我们可以这样导入:
import { add, subtract } from './math.js'; console.log(add(2, 3)); // 输出:5 console.log(subtract(5, 3)); // 输出:2
引入所有导出内容
可以使用 * 引入模块中所有的命名导出,并将它们绑定到一个对象上。
-
示例:
import * as math from './math.js'; console.log(math.add(2, 3)); // 输出:5 console.log(math.subtract(5, 3)); // 输出:2
常见问题
1. 默认导出和命名导出不能混淆
如果使用了默认导出,不能用命名导出的语法引入,反之亦然。
// 错误示例:math.js
export default function add(a, b) {
return a + b;
}
// 错误导入:
import { add } from './math.js'; // 报错:add is not exported
正确方式:
import add from './math.js';
2. 文件路径问题
-
如果模块和引入文件在不同目录下,路径必须正确。
-
示例路径:
- 当前目录:
"./module.js" - 父目录:
"../module.js" - 子目录:
"./subdir/module.js"
- 当前目录:
3. 浏览器支持
在 HTML 文件中必须使用 <script type="module"> 才能使用 import 和 export:
<script type="module" src="./main.js"></script>