JavaScript生产环境常用设计模式是解决实际问题的自然实践:模块封装(export/import)、观察者模式(EventTarget)、工厂函数、策略模式(对象字典替代if/else),重在提升可维护性而非套用概念。

JavaScript 中真正被广泛用在生产环境的设计模式,不是教科书里的抽象分类,而是解决具体问题时自然沉淀下来的实践。下面这几个,你几乎每天都在写,只是没给它们贴上“模式”标签。
模块封装:用 export / import 替代 IIFE 和全局污染
ES6 模块系统已成事实标准,export 和 import 不仅是语法糖,更是显式依赖声明和作用域隔离的保障。老项目里常见的 IIFE 封装((function(){...})())现在只在极少数需要立即执行且不暴露任何变量的场景下才用。
- 避免在模块顶层直接执行副作用代码,把初始化逻辑收进函数(如
initApp()),便于测试和按需加载 -
export default适合单例或主入口;命名导出(export const utils = {...})更适合工具集合,支持 tree-shaking - 注意循环依赖:A 导入 B,B 又导入 A → Node.js 会返回一个空对象,Vite/Webpack 可能报
Cannot access 'X' before initialization
观察者模式:用 EventTarget 实现轻量通信
不用再手写 on()/emit(),现代浏览器原生 EventTarget 已足够可靠,尤其适合组件间松耦合通信或状态变更通知。
- 自定义事件名建议加前缀避免冲突,比如
ui:tab-change或data:fetch-success -
dispatchEvent()是同步的,如果事件处理函数耗时长,会阻塞主线程;异步场景可包装成Promise或配合queueMicrotask() - React/Vue 组件中慎用全局
EventTarget,容易忘记removeEventListener()导致内存泄漏
工厂函数:替代构造函数 + new 的更灵活创建方式
比起 class 和 new,工厂函数(返回普通对象)更轻量、更易组合、天然支持私有数据闭包,且不涉及原型链陷阱。
立即学习“Java免费学习笔记(深入)”;
- 典型写法:
const createButton = (label, onClick) => ({ label, onClick, render() { ... } }) - 工厂内部可自由混用 class 实例、其他工厂结果、甚至 Promise,而
class构造函数不能await - 若需类型提示,TypeScript 中用
interface或type描述返回值,比class的instanceof判断更准确 - 不要为了“模式”而工厂化——简单对象字面量(
{ x: 1 })永远比多一层函数调用更直接
策略模式:用对象字典替代一长串 if/else 或 switch
当业务逻辑分支随配置或用户行为动态变化时,把每个分支抽成独立函数,挂到一个对象上,通过键名查找执行,比硬编码条件判断更易维护。
- 示例:
const handlers = { 'email': sendEmail, 'sms': sendSMS, 'push': sendPush },然后handlers[type]?.(data) - 键名最好来自受控来源(如后端枚举、常量定义),避免拼写错误导致
undefined is not a function - 策略函数应保持纯或至少无副作用,否则调试时难以复现行为
- 如果策略间共享状态,别藏在闭包里——显式传参或用单独的状态管理对象,否则测试和复用都会变难
设计模式的价值不在“用了多少种”,而在是否让某段代码从“改起来心慌”变成“加个新 case 就完事”。很多所谓“模式”在 JS 里只是几行自然写法,强行套概念反而增加理解成本。











