当前位置: 首页 > news >正文

易混淆的CommonJS和ESM(ES Module)及它们区别

前言:
【CommonJs】exports,modules.exports,require的区别

📌概念

1. CommonJS 概念

历史:早期 JavaScript 主要跑在浏览器,没有模块系统;Node.js 为了管理代码,引入了 CommonJS 规范。

核心特点:

  • require() 导入模块
  • module.exportsexports 导出模块
  • 模块在运行时加载(同步加载)
  • 每个文件就是一个独立作用域

👉 示例:

// foo.js
module.exports = { a: 1 };// bar.js
const foo = require('./foo');
console.log(foo.a); // 1

2. ESM (ES Module) 概念

历史:ES6(2015)标准化了 JavaScript 原生模块系统,叫 ESM。

核心特点:

  • import 导入
  • export 导出
  • 模块在 编译时 静态解析(比 CommonJS 更高效)
  • 支持 tree-shaking(去掉没用到的代码)
  • 既能在浏览器直接运行,也能在 Node.js(新版本)中使用

👉 示例:

// foo.js
export const a = 1;// bar.js
import { a } from './foo.js';
console.log(a); // 1

📌区别

CommonJS vs ESM 的区别

对比维度CommonJSESM
语法require / module.exportsimport/ export
加载时机运行时加载(同步)编译时加载(静态)
导出方式整个对象(module.exports)默认导出 + 具名导出
导入结果require() 拿到的是对象副本import 拿到的是 绑定的引用
Tree Shaking❌ 不支持✅ 支持(Webpack、Rollup 等)
是否动态✅ 可以写 require(someVar) 动态导入❌ 只能静态导入(不过有 import() 动态语法)
执行顺序按代码执行顺序加载静态依赖分析后再执行
Node 默认支持✅ (默认)✅ (需 .mjs 后缀 或 package.json "type": "module")
浏览器支持❌ 原生不支持(需打包工具)✅ 现代浏览器原生支持 <script type="module">

📌使用场景

场景

CommonJS:

  • 主要在 Node.js 老项目中使用(兼容性好)
  • 适合脚本、工具类项目

ESM:

  • 现代前端开发的主流选择(React, Vue, Angular 全部用 ESM)
  • Tree-shaking、静态分析、跨平台更优
  • Node.js 16+ 也推荐逐步迁移到 ESM

直观理解

CommonJS 像是:“我执行到这里,才去加载另一个文件”。
ESM 像是:“我在编译时就知道要依赖哪些文件,先解析好,再运行”。

1. CommonJS (Node 里默认用的)

写法:require
导出方式:

// foo.js
// 方法1:exports
exports.a = 1;
exports.sayHi = () => console.log('hi');// 方法2:module.exports
module.exports = {b: 2,sayBye: () => console.log('bye')
};

导入方式:

const foo = require('./foo.js');
console.log(foo.a); // 1
foo.sayHi();        // hi
console.log(foo.b); // 2
foo.sayBye();       // bye

👉 CommonJS 里只有 require,没有 import {} 的语法。

2. ES Module (ESM,现代写法)

写法:import
导出方式:

// foo.mjs 或者 package.json 里加 "type": "module"
// 默认导出(只能有一个)
export default function() {console.log('default fn');
}// 具名导出(可以有多个)
export const a = 1;
export function sayHi() { console.log('hi'); }

导入方式:

// 默认导入
import foo from './foo.js'; 
foo(); // default fn// 具名导入
import { a, sayHi } from './foo.js';
console.log(a); // 1
sayHi();        // hi

3. 关键区别:import xxx vs import { xxx }

写法对应导出特点
import xxx from ‘./foo.js’export default …只能对应 一个默认导出
import { xxx } from ‘./foo.js’export const xxx = … / export function xxx…对应 具名导出,可以同时导入多个
import * as all from ‘./foo.js’所有导出(默认 + 具名)用对象的方式访问

4. CommonJS 和 ESM 混用情况

Node 现在也支持 import,但规则有点复杂:
如果模块是用module.exports = { ... }导出的:

// foo.js (CommonJS)
module.exports = { a: 1, b: 2 };// ESM 导入
import foo from './foo.js';    // 默认导入
console.log(foo.a); // 1import { a } from './foo.js';  // ❌ 会报错,找不到具名导出

如果模块是用exports.a = ... 导出的:
结果和上面一样,import {a} 在 ESM 里也不生效。
👉 所以 CommonJS 导出的对象 = ESM 的默认导出。

记忆口诀:

  • CommonJSmodule.exports 导出啥,require() 就拿到啥。
  • ESMexport default 对应 import xxxexport const xxx 对应 import { xxx }
http://www.dtcms.com/a/344503.html

相关文章:

  • 工控/医疗设备没有连接网络,贝锐向日葵Q1破解远程运维难题
  • 【ElasticSearch】IK分词器安装,配置修改,支持新增词组,中文常用mapping使用案例
  • Python 中 SQLAlchemy 和 MySQLdb 的关系
  • MongoDB 分片集群把非分片集合转成分片集合
  • MySQL 错误码
  • Flutter Provider 详解:从状态管理痛点到实战落地
  • Linux权限详解
  • 电子基石:硬件工程师的器件手册 (十三) - 电源管理IC:能量供给的艺术
  • 使用html+css+javascript练习项目布局--创建导航栏
  • 高并发场景数据与一致性的简单思考
  • 理解音频响度:LUFS 标准及其计算实现
  • 在灵码中配置MCP服务
  • Basic Threejs (2)
  • Unity中国小游戏行业沙龙:抖音小游戏平台分析与规划
  • Excel处理控件Aspose.Cells教程:使用Python将 Excel 转换为 NumPy
  • AWS OpenSearch 是什么
  • 复合设计模式
  • 阿里云详解:与 AWS、GCP 的全方位比较
  • openEuler系统中home文件夹下huawei、HwHiAiUser、lost+found 文件夹的区别和作用
  • 农业-学习记录
  • vue中监听页面滚动位置
  • Playwright进阶指南 (5):拦截与模拟网络请求
  • 【LLMs篇】19:vLLM推理中的KV Cache技术全解析
  • SymPy 中抽象函数的推导与具体函数代入
  • 《器件在EMC中的应用》---磁珠在EMC中的应用
  • 一次性密码(OTP)原理及应用
  • 解决 PyTorch 导入错误:undefined symbol: iJIT_NotifyEvent
  • 数据结构之深入探索快速排序
  • Spring Start Here 读书笔记:第10章 Implementing REST services
  • vue vxe-gantt 甘特图自定义任务条样式模板 table 自定义插槽模板