javascript模块化通过闭包实现私有封装,函数作用域天然隔离内部变量,仅return对象暴露接口;特权函数可访问私有数据,外部无法直接操作;命名强调能力而非实现;支持单例与多实例工厂模式;需妥善处理this绑定与异步时机,并提供destroy清理资源。

JavaScript 中模块化利用闭包暴露接口,本质是靠函数作用域天然“锁住”内部变量和函数,只把真正需要对外协作的方法或属性,通过 return 的对象 显式交出去。这不是语法限制,而是设计契约——没被返回的,外部就真的碰不到。
用函数作用域当隔离墙
所有用 let、const 或 var 在函数内声明的变量、函数,默认就在闭包里“上锁”。外部连 typeof module.privateData 都会报错,更别说修改。
- 私有数据不挂到返回对象上,比如避免
return { cache }或return { _config } - 返回对象里的每个方法(如
get()、init())是“特权函数”,能读写私有数据,但调用方无法绕过它们直接操作 - 哪怕只是
return { version: '1.0' },这个version是只读副本;若想可变,必须提供setVersion()方法来控制
返回对象就是你的对外契约
这个对象不是随便列几个键,而是你向使用者承诺的全部能力。命名要直说“能做什么”,不说“怎么做的”。
- 行为类接口用动词开头:
save()、reset()、subscribe() - 状态或能力类用名词/形容词:
isReady、defaults、retryCount - 不暴露中间状态,比如不用
getInternalState(),而用getState()或onStateChange(cb)
支持多实例与配置初始化
单例用 IIFE,多实例必须用工厂函数——每次调用都生成独立闭包,各实例状态互不干扰。
- 配置作为参数传入外层函数,内部设好默认值,例如
timeout: config.timeout ?? 3000 - 初始化逻辑(如预加载、绑定事件、启动定时器)放在闭包开头执行
- 不同模块调用同一工厂函数,各自持有自己的私有数据,比如
createApi({ baseUrl: '/user' })和createApi({ baseUrl: '/order' })完全隔离
处理 this 和异步时机
暴露的方法一旦被当回调使用(如传给 addEventListener 或 setTimeout),原始上下文容易丢失;异步操作完成前,数据可能还没准备好。
- 需要保持
this的方法,可用箭头函数、.bind(this),或在返回对象里预先绑定 - 异步场景下,
getData()不应返回未就绪的值,而应返回Promise,或等初始化完成后再 resolve 整个模块 - 提供
destroy()方法,在其中清除定时器、监听器、中断请求,确保卸载后能被垃圾回收
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











