JavaScript 模块化:深入理解 export 和 import 语法
在现代 JavaScript 开发中,模块化是组织代码的基础。本文将深入探讨 JavaScript 模块系统中的 export 和 import 语法,帮助你掌握模块化的核心概念。
基础导出语法
声明前导出
最简单的导出方式是在声明前添加 export
关键字:
// 导出变量
export let months = ['Jan', 'Feb', 'Mar'];
// 导出常量
export const MODULES_YEAR = 2015;
// 导出类
export class User {
constructor(name) {
this.name = name;
}
}
重要提示:当 export
用于类和函数前时,它仍然是函数/类声明,而不是表达式。因此不需要在结尾添加分号,这与 JavaScript 风格指南一致。
声明后导出
你也可以先声明,再统一导出:
function sayHi(user) {
console.log(`Hello, ${user}!`);
}
function sayBye(user) {
console.log(`Bye, ${user}!`);
}
export {sayHi, sayBye}; // 导出列表
这种方式更灵活,适合需要集中管理导出的场景。
导入方式详解
基本导入
最直接的导入方式是使用花括号指定要导入的内容:
import {sayHi, sayBye} from './say.js';
sayHi('John'); // Hello, John!
sayBye('John'); // Bye, John!
命名空间导入
当需要导入大量内容时,可以使用命名空间导入:
import * as say from './say.js';
say.sayHi('John');
say.sayBye('John');
虽然这种方式看起来简洁,但有以下缺点:
- 代码可读性降低(
say.sayHi()
比直接sayHi()
冗长) - 难以快速了解模块依赖关系
- 不利于代码重构和静态分析
别名导入/导出
可以使用 as
关键字创建别名:
// 导入时创建别名
import {sayHi as hi, sayBye as bye} from './say.js';
hi('John'); // Hello, John!
bye('John'); // Bye, John!
// 导出时创建别名
export {sayHi as hi, sayBye as bye};
别名在以下场景特别有用:
- 避免命名冲突
- 缩短长名称
- 提供更符合当前上下文的名称
默认导出
默认导出是模块系统的特殊语法,适用于"一个模块一个主要功能"的场景。
基本用法
// 📁 user.js
export default class User {
constructor(name) {
this.name = name;
}
}
// 📁 main.js
import User from './user.js'; // 注意没有花括号
new User('John');
默认导出的特点:
- 每个文件只能有一个默认导出
- 导入时不需要花括号
- 可以导出匿名实体(类、函数、值等)
默认导出的争议
虽然默认导出很流行,但它有一些潜在问题:
- 导入时可以随意命名,导致团队代码不一致
- 自动补全支持不如命名导出好
- 重导出语法更复杂
许多团队选择始终使用命名导出,即使模块只导出一个东西,以保持一致性。
重导出模式
重导出允许你将其他模块的内容重新导出,这在创建库或组织大型项目时非常有用。
基本重导出
export {sayHi} from './say.js'; // 直接重导出
export {default as User} from './user.js'; // 重导出默认导出
实际应用场景
想象你正在构建一个认证库,目录结构如下:
auth/
index.js // 主入口
user.js // 用户相关
helpers.js // 辅助函数
providers/ // 第三方认证提供者
github.js
facebook.js
index.js
作为统一入口可以这样组织:
// 重导出辅助函数
export {login, logout} from './helpers.js';
// 重导出用户类
export {default as User} from './user.js';
// 重导出提供者
export {default as Github} from './providers/github.js';
export {default as Facebook} from './providers/facebook.js';
这样使用者只需从主入口导入:
import {login, User, Github} from 'auth/index.js';
处理默认导出的注意事项
重导出默认导出需要特殊语法:
// 正确方式
export {default as User} from './user.js';
// 错误方式
export User from './user.js'; // 语法错误
如果需要同时重导出命名导出和默认导出:
export * from './user.js'; // 重导出命名导出
export {default} from './user.js'; // 重导出默认导出
最佳实践总结
-
模块设计原则:
- 单一职责:每个模块只做一件事
- 明确接口:通过导出定义清晰的模块边界
- 避免混合导出:一个模块最好只使用命名导出或默认导出
-
导入建议:
- 优先使用明确导入(
import {func} from 'module'
) - 限制使用命名空间导入(
import * as module
) - 保持导入名称与导出名称一致
- 优先使用明确导入(
-
项目组织:
- 使用重导出创建清晰的公共API
- 将内部实现细节隐藏在模块内部
- 保持目录结构反映模块层次
掌握这些模块化技术将显著提升你的 JavaScript 代码组织能力,使项目更易维护和扩展。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考