闭包是实现轻量级函数状态机的理想工具,通过内部变量封装私有状态并返回操作接口,支持多状态、守卫与副作用,适用于表单流程、UI交互等局部确定性场景。

闭包可以自然地封装状态和行为,是实现轻量级函数状态机的理想工具——无需类、不依赖外部变量,状态完全私有且随函数生命周期存在。
用闭包保存当前状态与转移逻辑
状态机的核心是“当前状态”和“状态转移规则”。闭包通过内部变量保存状态,通过返回的函数暴露操作接口,每次调用只影响自身闭包内的状态。
例如,一个开关状态机(on/off)可这样实现:
function createToggle() {
let state = 'off';
return {
toggle() {
state = state === 'off' ? 'on' : 'off';
return state;
},
getState() {
return state;
},
reset() {
state = 'off';
}
};
}
const light = createToggle();
console.log(light.toggle()); // 'on'
console.log(light.toggle()); // 'off'
console.log(light.getState()); // 'off'
支持多状态与自定义动作的增强版
将状态定义为枚举,转移逻辑抽离为配置对象,让状态机更清晰、易扩展。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
关键点:状态变更前可插入守卫(guard)、变更后可触发副作用(effect)。
function createStateMachine(initial, config) {
let state = initial;
return {
getState() { return state; },
send(event) {
const transition = config[state]?.[event];
if (!transition) return false;
const { target, guard, effect } = transition;
if (guard && !guard()) return false;
state = target;
if (effect) effect();
return true;
}
};
}
// 使用示例:订单状态机
const orderSM = createStateMachine('draft', {
draft: {
submit: { target: 'pending', effect: () => console.log('已提交') }
},
pending: {
approve: { target: 'confirmed', effect: () => console.log('已批准') },
reject: { target: 'rejected', effect: () => console.log('已拒绝') }
}
});
orderSM.send('submit'); // → 'pending', 打印"已提交"
orderSM.send('approve'); // → 'confirmed', 打印"已批准"
避免常见陷阱:状态隔离与内存管理
每个闭包实例独立维护状态,这是优势,但也意味着不能误用共享引用。
- 不要把闭包返回的对象直接赋值给全局或多个地方共用,否则状态会意外共享
- 若状态包含大型数据(如缓存对象),在不需要时可通过重置或置 null 主动释放,防止内存泄漏
- 避免在闭包内长期持有 DOM 节点或事件监听器——状态机结束时应清理副作用
适合哪些场景?
闭包状态机轻巧灵活,特别适用于:
- 表单步骤流程(如注册三步:填写→验证→完成)
- UI 组件交互状态(按钮加载中/禁用/成功态)
- 协议解析器中的解析阶段管理(header→body→footer)
- 动画帧控制(idle→playing→paused→ended)
它不替代 Redux 或 XState 等完整状态管理方案,但在局部、确定性、低耦合的逻辑中,简洁而有力。

















