ES6模块与CommonJS模块在执行上下文层面存在根本差异:ES6顶层this为undefined、自动严格模式、静态解析+实时绑定导出;CommonJS顶层this指向module.exports、默认非严格模式、同步执行+值拷贝导出。

ES6 模块和 CommonJS 模块在执行上下文层面存在根本性差异,这直接影响 this 的指向、严格模式行为、作用域初始化时机等关键运行表现。
顶层 this 的值完全不同
在 CommonJS 中,每个模块文件的顶层作用域里,this 明确指向 module.exports 对象,因此可以直接用 this.xxx = yyy 做导出:
-
CommonJS 示例:
this.greet = () => console.log('hi');等价于module.exports.greet = ... -
ES6 模块中:
this在顶层始终为undefined,任何对this的赋值或读取都会得到undefined,且无法用于导出
严格模式是否自动启用
ES6 模块代码**自动处于严格模式**,无需写 "use strict";而 CommonJS 模块默认是非严格模式,只有显式声明才会启用严格模式:
- 这意味着在 ES6 模块中,静默失败的操作(如给不可写属性赋值、使用八进制字面量)会直接抛
TypeError或SyntaxError - CommonJS 下若未开启严格模式,某些不安全操作可能被忽略,带来隐蔽的兼容性风险
模块执行时机与作用域绑定顺序
CommonJS 是“边加载边执行”:require 语句执行时,立刻同步运行目标模块全部顶层代码,并缓存 module.exports 的最终快照;ES6 模块则先完成整个依赖图的静态解析,再按拓扑顺序执行——但导出绑定是**实时、活引用**的:
- 一个 ES6 模块中
export let count = 0;,另一个模块import { count } from './a.js',后续在 a.js 中修改count++,导入方能立即看到变化 - CommonJS 中
exports.count = 0;导出的是初始值的拷贝,后续修改原变量不影响已导出的对象属性(除非导出的是对象本身,且修改其内部属性)
模块作用域中的全局变量可见性
两者都提供模块级作用域,但对全局对象(如 globalThis、window、global)的访问逻辑一致;区别在于——
- CommonJS 模块中可安全访问
global(Node.js)或window(浏览器 CJS 环境),且require、module、__filename等是注入的局部变量 - ES6 模块中没有
require或__dirname这类变量,需通过import.meta.url配合new URL(..., import.meta.url)获取路径,globalThis是唯一推荐的跨环境全局对象访问方式


















