ES6和CommonJS模块区别

ES6 模块(ESM)和 CommonJS 是 JavaScript 中两种主要的模块规范,它们在设计理念、语法和行为上有显著区别。以下是两者的核心差异:

1. 语法规范与用途

  • •

    ES6 模块(ESM)

    是 ECMAScript 2015 标准化的模块系统,适用于浏览器和 Node.js(需显式启用),是 JavaScript 官方模块规范。

    核心关键字:export、import、export default。

  • •

    CommonJS

    是 Node.js 原生的模块规范,主要为服务器端设计,早期用于解决 Node.js 中的模块依赖问题。

    核心关键字:module.exports、exports、require()。

2. 导出 / 导入语法

操作 ES6 模块(ESM) CommonJS
默认导出 export default { ... } module.exports = { ... }
命名导出 export const a = 1; export function f() {} exports.a = 1; exports.f = function() {}
导入默认 import obj from './module.js' const obj = require('./module.js')
导入命名 import { a, f } from './module.js' const { a, f } = require('./module.js')

3. 加载时机与方式

  • •

    ES6 模块:静态加载

    • •

      导入和导出语句在代码解析阶段执行(编译时加载),而非运行时。

    • •

      导入路径必须是静态字符串(不能动态拼接)。

    • •

      支持 import() 动态导入(返回 Promise)。

    示例:

    javascript

    运行
    --javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

    复制代码
    // 静态导入(解析时执行)
    import { utils } from './tools.js';
    
    // 动态导入(运行时执行)
    import('./tools.js').then(module => { ... });
  • •

    CommonJS:动态加载

    • •

      导入(require())在代码运行阶段执行,支持动态路径。

    • •

      模块加载是同步的(Node.js 中对本地模块有缓存优化)。

    示例:

    javascript

    运行
    --javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

    复制代码
    // 支持动态路径
    const path = './tools.js';
    const utils = require(path);

4. 模块输出的本质

  • •

    ES6 模块:值的引用

    • •

      导出的是值的只读引用,模块内部值变化时,导入方会同步更新。

    • •

      导入的变量是只读的(不能重新赋值)。

    示例:

    javascript

    运行
    --javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

    复制代码
    // module.js
    export let count = 0;
    export function increment() { count++; }
    
    // main.js
    import { count, increment } from './module.js';
    increment();
    console.log(count); // 输出 1(跟随模块内部变化)
  • •

    CommonJS:值的拷贝

    • •

      导出的是值的拷贝(对象导出的是引用地址的拷贝),模块内部值变化不影响导入方。

    • •

      导入的变量可以重新赋值。

    示例:

    javascript

    运行
    --javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

    复制代码
    // module.js
    let count = 0;
    module.exports = {
      count,
      increment: () => { count++; }
    };
    
    // main.js
    const { count, increment } = require('./module.js');
    increment();
    console.log(count); // 输出 0(拷贝的值未更新)

5. 循环依赖处理

  • •

    ES6 模块

    由于静态解析,模块在加载时会先创建「模块记录」,循环依赖时能正确引用未完全初始化的模块(返回部分导出值)。

  • •

    CommonJS

    循环依赖时,会返回模块当前已执行部分的导出值(可能是不完整的),依赖后续执行补充。

6. 顶层 this****指向

  • •

    ES6 模块:顶层 this 为 undefined。

  • •

    CommonJS:顶层 this 指向当前模块的 module.exports。

7. 使用场景

  • •

    ES6 模块

    • •

      浏览器环境(原生支持,需在 <script type="module"> 中使用)。

    • •

      现代前端工程(Vue、React 项目,通过 Webpack/Vite 打包)。

    • •

      Node.js 13.2+(需在 package.json 中设置 "type": "module")。

  • •

    CommonJS

    • •

      Node.js 环境(默认模块系统)。

    • •

      早期 Node.js 生态的库(如 Express 中间件)。

总结

特性 ES6 模块(ESM) CommonJS
加载时机 解析时(静态) 运行时(动态)
输出本质 值的引用(只读) 值的拷贝(可修改)
循环依赖处理 基于模块记录(更可靠) 基于执行状态(可能不完整)
适用环境 浏览器 + 现代 Node.js Node.js 原生
动态导入支持 import()(返回 Promise) require() 天然支持

现代前端开发以 ES6 模块为主,而 CommonJS 主要用于 Node.js 后端开发。在实际项目中,两者可通过打包工具(如 Webpack)相互兼容。

相关推荐
Csvn2 小时前
性能监控
前端
Csvn2 小时前
构建工具
前端
FRing032 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
kyriewen5 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒5 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫5 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus6 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude
孟陬7 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端
Zhao-Jichao7 小时前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端
Highcharts.js8 小时前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化