闭包在状态机中主要用于封装和持久化状态值,避免全局变量污染,通过外层函数作用域保存状态变量,使返回的方法共享同一闭包环境实现状态受控变更。

闭包在状态机中主要用于**封装和持久化状态值**,避免全局变量污染,同时让状态转换逻辑清晰、可复用。核心思路是:用函数返回一个对象(或一组函数),该对象的方法能访问并修改外层函数作用域中定义的状态变量——这个变量就是当前状态值,而所有方法共享同一份闭包环境,从而实现状态的保存与受控变更。
用闭包封装状态变量和转换逻辑
把状态值(如 currentState)声明在外部函数作用域内,内部返回的方法(如 transition、getState)通过闭包持续持有对该变量的引用:
function createStateMachine(initialState) {
let state = initialState;
return {
getState() {
return state;
},
transition(nextState) {
// 可加入校验、副作用等
state = nextState;
return this; // 支持链式调用
},
reset() {
state = initialState;
return this;
}
};
}
const fsm = createStateMachine('idle');
console.log(fsm.getState()); // 'idle'
fsm.transition('loading').transition('success');
console.log(fsm.getState()); // 'success'
支持有限状态转换(带规则约束)
真实场景中并非任意跳转,需限制合法状态迁移。可在闭包中预存状态转移表(transitions),让 transition 方法校验后再更新:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 状态表定义为对象,键为当前状态,值为允许跳转到的状态数组
-
transition先检查是否允许跳转,再更新闭包内的state - 错误跳转可抛出异常或静默忽略,取决于设计需求
function createValidatedFSM(initialState, transitions) {
let state = initialState;
return {
getState() { return state; },
transition(target) {
const allowed = transitions[state] || [];
if (!allowed.includes(target)) {
throw new Error(`Invalid transition: ${state} → ${target}`);
}
state = target;
return this;
}
};
}
const userFSM = createValidatedFSM('unverified', {
unverified: ['verified', 'banned'],
verified: ['suspended', 'banned'],
suspended: ['verified', 'banned']
});
userFSM.transition('verified'); // ✅
// userFSM.transition('suspended'); // ❌ 报错
结合事件驱动实现响应式状态机
闭包还可配合事件监听(如自定义事件、Promise 回调),让状态变化触发副作用,同时保持状态私有:
立即学习“Java免费学习笔记(深入)”;
- 在闭包中维护状态 + 事件回调列表(
listeners) - 每次
transition后遍历调用监听器,并传入新旧状态 - 监听器无法直接修改
state,只能响应,保障状态可控
function createEventFSM(initialState) {
let state = initialState;
const listeners = [];
return {
onStateChange(cb) {
listeners.push(cb);
return () => {
const i = listeners.indexOf(cb);
if (i > -1) listeners.splice(i, 1);
};
},
transition(next) {
const prev = state;
state = next;
listeners.forEach(cb => cb({ prev, next }));
return this;
}
};
}
const loggerFSM = createEventFSM('off');
loggerFSM.onStateChange(({ prev, next }) =>
console.log(`Switched from ${prev} to ${next}`)
);
loggerFSM.transition('on'); // 输出: Switched from off to on
注意事项与常见误区
使用闭包实现状态机时需注意:
- 每个调用
createStateMachine()都生成独立闭包,多个实例互不影响——这是优点,也是设计前提 - 不要在闭包外暴露对状态变量的直接引用(如返回
state的引用或让它参与外部运算),否则破坏封装性 - 若需序列化状态(如存 localStorage),应通过显式方法(如
serialize())导出,而非暴露闭包变量 - 避免在闭包中保留大型对象或 DOM 引用,防止内存泄漏

















