JavaScript模块默认封闭:顶层声明仅本模块可见,不export则外部无法访问,export明确暴露接口,无需IIFE保护,动态import同样遵循作用域隔离。

JavaScript 中用 import 实现作用域隔离,核心在于模块的**默认封闭性**:每个 ES 模块天然拥有独立的作用域,顶层声明(const、let、function、class)不会污染全局,也不会被其他模块直接访问——除非显式 export。
模块自动私有,无需额外封装
与脚本(<script>)不同,ES 模块默认启用严格模式,且顶层变量/函数仅在当前模块内有效:
-
const internal = '仅本模块可见';—— 其他模块import过来也拿不到它 - 即使两个模块都声明了
const helper = () => {},它们互不影响,不存在命名冲突 - 没有
export的内容,外部无法通过任何方式访问(包括动态import()返回的命名空间对象)
只暴露需要共享的接口
用 export 明确“开门”,控制对外可见的部分:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
export const api = { get() {}, post() {} };→ 导出一个对象,使用者解构或点取 -
export function init() {}→ 命名导出,支持按需导入:import { init } from './module.js' -
export default class Renderer {}→ 默认导出,导入时可自定义名称:import MyRenderer from './module.js'
避免意外泄露:不导出就安全
常见误区是以为要手动用 IIFE 或块级作用域“保护”模块内部。其实不用:
立即学习“Java免费学习笔记(深入)”;
- 模块文件中写
var globalLeak = 123;?它依然只在模块内,不会变成window.globalLeak - 即便模块里调用
eval('var x = 42'),x 也只在 eval 执行上下文中,不影响模块顶层作用域 - 真正要防的是误写
export { secretKey }或把敏感值挂到导出对象上
动态导入也遵守同一规则
import() 返回 Promise,解析后得到的模块命名空间同样受作用域限制:
-
const m = await import('./utils.js');→m是只读命名空间对象,仅含该模块export的内容 -
m.internalHelper是undefined(如果internalHelper没被导出) - 动态导入的模块本身仍保持独立作用域,不会和主模块“融合”

















