JavaScript 模块化详解:CommonJS、ES Module 到底有什么区别?

17 阅读2分钟

前言

当项目代码越来越多时,如果所有变量、函数、对象都写在一个文件中,就会带来很多问题:

  • 容易命名冲突
  • 不方便协作
  • 代码难维护
  • 功能难复用

所以 JavaScript 需要 模块化

模块化并不只是“把代码拆分成多个文件”,更重要的是:

让每个文件都有自己的作用域,并且可以通过导入和导出组织代码。

本文就来系统讲清楚 JavaScript 模块化的发展和常见方案。


一、为什么需要模块化?

早期 JavaScript 没有模块系统,大家通常把变量和函数直接写到全局作用域中:

var name = 'Tom';

function getUser() {
  return name;
}

如果多个文件都写同名变量,就容易冲突。

模块化的出现,就是为了解决这些问题:

  • 避免全局污染
  • 提高代码复用
  • 方便拆分文件
  • 便于团队协作
  • 提高可维护性

二、早期模块化:IIFE

在 ES Module 出现之前,经常用立即执行函数来模拟模块作用域。

const userModule = (function () {
  let name = 'Tom';

  function getName() {
    return name;
  }

  function setName(newName) {
    name = newName;
  }

  return {
    getName,
    setName
  };
})();

console.log(userModule.getName()); // Tom

这种方式本质上利用了 闭包

特点:

  • 可以创建私有作用域
  • 能避免部分全局污染
  • 但不够标准,维护成本高

三、CommonJS

CommonJS 是 Node.js 中常见的模块化规范。

导出

// math.js
function add(a, b) {
  return a + b;
}

module.exports = {
  add
};

导入

// app.js
const math = require('./math');

console.log(math.add(1, 2)); // 3

特点:

  • 主要用于 Node.js

  • 使用

    require

    导入

  • 使用

    module.exports

    导出

  • 同步加载


四、ES Module(ESM)

这是现在最主流、最推荐的模块化方案。

命名导出

// math.js
export function add(a, b) {
  return a + b;
}

export function sub(a, b) {
  return a - b;
}

导入:

import { add, sub } from './math.js';

console.log(add(1, 2));
console.log(sub(5, 3));

默认导出

// user.js
export default function getUser() {
  return { name: 'Tom' };
}

导入:

import getUser from './user.js';

console.log(getUser());

五、命名导出和默认导出的区别

命名导出

export const name = 'Tom';

导入时必须使用对应名字:

import { name } from './file.js';

默认导出

export default function () {}

导入时名字可以自定义:

import myFn from './file.js';

六、CommonJS 和 ES Module 的区别

CommonJS

const math = require('./math');
module.exports = { add };

ES Module

import { add } from './math.js';
export { add };

常见区别:

  • CommonJS 多用于 Node.js 传统环境
  • ES Module 是 JavaScript 官方标准模块系统
  • CommonJS 是同步加载
  • ES Module 更适合现代前端工程化

七、模块化的实际意义

模块化最大的价值是让代码更清晰。

比如一个项目可以拆成:

src
├── api
├── utils
├── components
├── views
└── store

每个模块负责不同功能,代码更容易维护。


八、总结

JavaScript 模块化的核心目标是:

把代码拆分成独立、可维护、可复用的模块。

学习模块化时,重点记住:

  • 早期有 IIFE

  • Node.js 常见 CommonJS

  • 现代前端主流是 ES Module

  • export / import是最常见写法