JavaScript 模块化那些事:从 IIFE 到 ES Modules
最早写前端的时候,经常是一个 index.html 里塞一大坨 <script>,变量到处飞,函数名一改项目全崩。后来慢慢开始接触各种模块化方案,从 IIFE、AMD、CommonJS 一路走到 ES Modules,心态也经历了从凑合能用到必须有规范。
这篇就当是给自己的一个小总结:为什么需要模块化、几种常见写法的区别、现在应该怎么写。
为什么要模块化?
几个非常现实的问题:
- 全局变量名冲突:不同文件里不小心定义了同名变量/函数。
- 依赖关系混乱:这个文件依赖谁?要先引哪个
<script>? - 代码难以拆分复用:逻辑越写越大,一改就牵一大片。
- 测试困难:无法只「拿出一小块」单独测试。
所以模块化要解决的就是:
把代码按职责拆成「小块」 + 明确每块对外暴露什么 + 明确依赖关系。
第一阶段:IIFE 模式(自执行函数)
当时 jQuery 时代最常见的一种写法,就是用自执行函数「造一个自己的小世界」。
(function () {
const API_URL = '/api/todos';
function fetchTodos() {
return fetch(API_URL).then(res => res.json());
}
function renderTodos(list) {
// 渲染逻辑...
}
window.todoApp = {
init() {
fetchTodos().then(renderTodos);
},
};
})();
特点:
- 用 IIFE 隔离出一个作用域,避免变量污染全局。
- 需要暴露给外面的东西挂在
window.todoApp上。 - 所有代码其实还是在一个文件里,没有真正意义上的「依赖管理」。
适合:小项目 / 简单封装。
不适合:多页面、多模块的大型项目。
第二阶段:AMD / RequireJS
再往后,就出现了 AMD(Asynchronous Module Definition),代表是 RequireJS。