export default 本身不创建闭包,真正实现极致封装的是在其后接立即执行的匿名函数表达式(iife),通过作用域隔离变量与函数,仅暴露最小接口,支持配置注入与状态维护,且需注意esm中必须用表达式形式而非函数声明调用。

export default 本身不创建闭包,它只是导出语法;真正实现“极致封装感”的局部业务闭包,靠的是在 export default 后面接一个立即执行的匿名函数表达式(IIFE),让变量、工具函数、状态等完全限定在函数作用域内,对外仅暴露最小接口。
用 IIFE 包裹业务逻辑,隔离内部实现
把整个模块逻辑写在一个匿名函数里,通过 return 显式声明对外暴露的内容。函数体内的所有声明(const、let、function)天然不可被外部访问。
- 内部变量不会污染全局或模块顶层作用域
- 可自由使用临时变量、私有辅助函数、缓存对象,无需担心命名冲突
- 适合封装带初始化逻辑、依赖预处理、或需维护内部状态的业务单元(如表单校验器、轮播控制器、请求重试管理器)
返回精简对象或函数,控制暴露粒度
return 的内容决定使用者能拿到什么。不是必须返回对象——也可以直接返回一个函数、类、甚至 Promise(如果初始化是异步的)。
- 若只提供单一能力,直接 return (params) => { ... },调用者看到的就是一个干净函数
- 若需多个方法 + 私有状态,return { init, submit, reset },内部共享闭包变量(如 let pending = false)
- 避免 return 内部 class 的实例(会暴露原型链),更推荐 return 封装后的纯函数对象
支持初始化参数与运行时注入
匿名函数可以接收参数,让闭包具备“配置能力”。常见做法是导出一个接受配置的工厂函数,再在其内部返回真正业务闭包。
- 第一层:export default (config) => { ... return { run, stop } }
- 第二层:在内部 IIFE 中捕获 config,形成稳定闭包环境
- 调用方按需传入 API 地址、超时时间、默认选项等,不侵入内部实现
- 示例:const uploader = require('./uploader')({ baseUrl: '/api' })
注意 CommonJS / ESM 差异与热更新兼容性
ESM 中 export default 是静态声明,因此不能直接写 export default (() => { ... })()(会报错:非法调用)。正确写法是:
- export default (() => { return { doX: () => {} }; })(); ✅ —— 表达式立即执行
- export default function() { ... }(); ❌ —— 语法错误,函数声明不能加括号调用
- 若模块需 HMR(热更新),确保闭包内无无法销毁的状态(如 setInterval、addEventListener),或提供 .dispose() 方法清理










