ES6 模块化导入导出详解

68 阅读3分钟

随着前端应用的日益复杂,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 的优势,最终产出更加优化的代码包。