1. 为什么我们需要模块化?
想象一下你正在开发一个大型JavaScript项目,所有代码都写在一个文件里。随着功能不断增加,这个文件可能膨胀到上万行代码。当你需要修改某个功能时,得在茫茫代码海中寻找相关片段;当多个开发者协作时,很容易出现命名冲突;当你想复用某个功能时,不得不复制粘贴整块代码——这就是没有模块化的噩梦。
模块化就像把乐高积木分门别类存放:
- 每个积木块(模块)有明确功能边界
- 通过标准接口(凸起和凹槽)相互连接
- 可以独立开发测试后再组装
- 损坏或升级单个部件不影响整体结构
在JavaScript发展历程中,先后出现了多种模块化方案。其中CommonJS和ES Module是目前最主流的两种标准,它们解决了以下核心问题:
- 依赖管理:明确声明模块间的依赖关系
- 作用域隔离:避免全局变量污染
- 代码复用:跨项目共享模块
- 按需加载:提升运行时性能
提示:虽然现代前端开发已经普遍采用ES Module,但了解CommonJS仍然很重要,因为:
- Node.js生态大量存量代码使用CommonJS
- 一些工具链(如Babel、Webpack)需要处理两种模块的互操作
- 理解差异有助于解决实际工程中的兼容性问题
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CommonJS:Node.js的模块化基石
2.1 基本语法与运行机制
CommonJS是2009年提出的规范,最初为服务器端JavaScript设计。Node.js采用并推广了这一标准,其核心语法非常简单:
javascript复制// 导出模块
module.exports = {
add: (a, b) => a + b,
PI: 3.1415926
}
// 或分开导出
exports.add = (a, b) => a + b
exports.PI = 3.1415926
// 导入模块
const math = require('./math')
console.log(math.add(2, 3)) // 5
关键特性:
- 同步加载:模块在首次require时立即加载并执行
- 缓存机制:相同路径的require()返回同一实例
- 值拷贝:导出的是值的拷贝(原始类型)或引用(对象类型)
2.2 实际应用中的注意事项
- 循环依赖处理:
javascript复制// a.js
exports.loaded = false
const b = require('./b')
console.log('在a中,b.loaded =', b.loaded)
exports.loaded = true
// b.js
exports.loaded = false
const a = require(
