随着前端应用的日益复杂,JavaScript 模块化开发已成为现代前端工程的标配。ES6(ECMAScript 2015)正式引入了官方的模块化语法,让我们能够更加优雅地组织和管理代码。本文将基于实际代码示例,详细介绍 ES6 模块的各种导入导出方式。
模块化的基本概念
在 ES6 之前,JavaScript 社区有多种模块化方案,如 CommonJS、AMD、CMD 等。ES6 模块化的出现为 JavaScript 提供了官方的、标准的模块系统,具有以下特点:
- 静态化:编译时就能确定模块的依赖关系
- 严格模式:默认使用严格模式
- 作用域隔离:每个模块都有自己的作用域
三种导出方式
1. 分别暴露(Named Exports)
分别暴露允许我们导出多个变量、函数或类,每个导出都需要明确的名称。
javascript
复制下载
// 1.js - 分别暴露
export let school = '张三';
export function teach(){
console.log('教你学前端');
}
2. 统一暴露(Named Exports)
统一暴露将所有需要导出的内容放在一个 export 语句中,更加集中和清晰。
javascript
复制下载
// 2.js - 统一暴露
let school = '张三';
function findJob(){
console.log('找工作');
}
export {school, findJob};
3. 默认暴露(Default Export)
默认暴露允许一个模块只导出一个默认值,这在使用第三方库或框架时非常常见。
javascript
复制下载
// 3.js - 默认暴露
export default{
school: 'ATGUIGU',
change: function(){
console.log('改变生活');
}
}
三种导入方式
1. 通用导入方式
使用 * as 语法可以将整个模块的内容导入到一个命名空间对象中。
html
复制下载运行
<!-- 1.html -->
<script type="module">
// 引入方式1: 通用的导入方式
import * as m1 from './src/1.js';
console.log(m1);
console.log(m1.school);
console.log(m1.teach());
import * as m2 from './src/2.js';
console.log(m2.school);
console.log(m2.findJob());
// 注意:默认暴露的模块需要通过 default 属性访问
import * as m3 from './src/3.js';
console.log(m3);
console.log(m3.default.school);
console.log(m3.default.change());
</script>
2. 解构赋值导入
通过解构赋值可以只导入需要的部分,减少代码体积和提高可读性。
html
复制下载运行
<!-- 2.html -->
<script type="module">
// 导入方式2:解构赋值形式
import { school, teach } from './src/1.js';
console.log(school);
console.log(teach());
// 处理命名冲突:使用 as 关键字起别名
import { school as zhangsan, findJob } from './src/2.js';
console.log(zhangsan);
console.log(findJob());
// 导入默认暴露的模块
import {default as m3} from './src/3.js';
console.log(m3);
console.log(m3.school);
console.log(m3.change());
</script>
3. 简便导入方式(仅限默认暴露)
对于默认暴露的模块,可以使用更加简洁的导入语法。
html
复制下载运行
<!-- 3.html -->
<script type="module">
// 导入方式3:简便形式 只针对默认暴露
import m3 from './src/3.js';
console.log(m3);
console.log(m3.school);
console.log(m3.change());
</script>
实际应用建议
1. 模块打包
在实际项目中,我们通常会将多个模块打包成一个或多个文件,以减少 HTTP 请求。可以使用 Webpack、Rollup 或 Vite 等构建工具:
javascript
复制下载
// app.js - 入口文件
import { school, teach } from './src/1.js';
import { school as zhangsan, findJob } from './src/2.js';
import m3 from './src/3.js';
// 在 index.html 中引入打包后的文件
// <script type="module" src="./app.js"></script>
2. 导出策略选择
- 使用分别暴露或统一暴露当模块需要提供多个功能时
- 使用默认暴露当模块主要提供一个主要功能或类时
- 可以同时使用默认暴露和命名暴露
javascript
复制下载
// 混合导出示例
export const config = { version: '1.0.0' };
export function helper() { /* ... */ }
export default class MainComponent { /* ... */ }
3. 导入最佳实践
- 使用解构赋值导入特定的功能,避免导入整个模块
- 使用有意义的别名解决命名冲突
- 将第三方库的导入放在文件顶部,自定义模块的导入放在其后
总结
ES6 模块化为 JavaScript 开发带来了革命性的变化,使得代码组织更加清晰,依赖管理更加明确。通过掌握不同的导入导出方式,我们可以根据具体场景选择最合适的模块化方案,提高代码的可维护性和可读性。
在实际项目中,结合构建工具使用 ES6 模块化,可以充分发挥其静态分析和 Tree Shaking 的优势,最终产出更加优化的代码包。