ES模块作用域天然隔离,每个模块拥有独立词法作用域,内部声明不自动暴露;需显式export/import控制可见性;同一模块多次导入共享单例作用域;默认严格模式杜绝隐式全局。

模块作用域隔离,指的是每个 ES Module 文件天然拥有独立的词法作用域,内部声明的变量、函数、类等不会自动暴露到全局,也不会被其他模块直接访问——除非显式通过 export 导出,并由其他模块用 import 主动引入。
模块作用域是私有的,不是“默认共享”的
在非模块脚本中(比如普通 <script>),var foo = 1 会挂到全局对象(如 window.foo);而写在 type="module" 脚本或 .js 模块文件里时,foo 只存在于该模块自己的作用域内。即使两个模块都声明了 const apiBase = 'https://api.example.com',它们互不影响,也不会覆盖彼此。
导出与导入决定可见性边界
模块不靠“命名空间”或“文件路径”来控制访问,而是靠语言级的 export/import 显式约定接口:
-
export const version = '1.2.0'→ 其他模块可通过import { version } from './config.js'获取 -
const helper = () => {}(未导出)→ 外部完全不可见,连同其闭包变量一起被封装 - 默认导出
export default class User {...}→ 导入时名字可自定义:import Person from './user.js'
模块执行一次,作用域只初始化一回
同一模块被多个地方 import,V8 引擎保证它只执行一次,且所有导入者共享该次执行产生的作用域结果。例如:
立即学习“Java免费学习笔记(深入)”;
模块 counter.js:
let count = 0; export const increment = () => ++count; export const getCount = () => count;
无论 A.js 和 B.js 都 import { increment } from './counter.js',它们操作的是同一个 count 变量——这是模块单例特性的体现,也是作用域隔离与复用的统一。
严格模式 + 无隐式全局,强化隔离效果
ES Modules 默认启用严格模式,禁止意外创建全局变量:
-
undeclared = 42→ 直接报ReferenceError,不会悄悄变成window.undeclared -
this在模块顶层为undefined,而非window或globalThis - 函数参数不能重名,八进制字面量(如
010)被禁用等,从语法层杜绝污染可能


















