javascript闭包如何实现状态机

来源:语言推理作者:相泽南头衔:网络博主
导读:本期聚焦于小伙伴创作的《javascript闭包如何实现状态机》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《javascript闭包如何实现状态机》有用,将其分享出去将是对创作者最好的鼓励。

javascript闭包的特性可以让函数保存自身作用域内的变量,这些变量不会被外部直接访问和修改,非常适合用来封装状态机的内部状态和转移逻辑,避免状态被意外篡改。

javascript闭包如何实现状态机

闭包与状态机基础概念

什么是javascript闭包

闭包是指有权访问另一个函数作用域中变量的函数,当函数执行完毕后,其执行上下文的作用域链不会被销毁,内部函数依然可以访问外部函数的变量。比如下面的简单示例:

function createCounter() {
  let count = 0; // 外部函数变量,被闭包保存
  return function() {
    count++;
    return count;
  };
}
const counter = createCounter();
console.log(counter()); // 输出1
console.log(counter()); // 输出2

这里的内部函数就形成了闭包,count变量被持续保存,每次调用counter都会修改并返回最新的count值。

什么是状态机

状态机全称有限状态机,由有限个状态、初始状态、状态转移规则和每个状态下的行为组成。它同一时间只能处于一个状态,接收到特定触发条件后会切换到另一个状态,同时执行对应状态的逻辑。常见的比如订单状态流转,从待支付到已支付再到已发货,就是典型的状态机场景。

用闭包实现状态机的核心思路

用闭包实现状态机可以把状态机的所有内部细节都封装在闭包内部,外部只能通过暴露的方法操作状态,核心思路分为三步:

  • 在闭包内部定义状态变量,存储当前状态,外部无法直接修改
  • 定义状态转移规则,明确每个状态下可以接收的触发事件,以及事件对应的下一个状态和要执行的行为
  • 暴露状态切换方法,外部通过调用该方法传入触发事件,闭包内部根据规则完成状态转移和逻辑执行

完整实现示例

下面以一个简单的灯光状态机为例,灯光有三个状态:关闭、低亮、高亮,触发事件是按下开关,按一次切换一个状态,循环流转。

// 状态机工厂函数,接收初始状态和状态配置
function createLightStateMachine(initState, stateConfig) {
  let currentState = initState; // 闭包保存当前状态,外部不可直接访问

  // 返回状态机操作对象
  return {
    // 触发事件,切换状态
    trigger(event) {
      const stateRule = stateConfig[currentState];
      if (!stateRule) {
        throw new Error(`当前状态${currentState}没有配置规则`);
      }
      const nextState = stateRule.transitions[event];
      if (!nextState) {
        throw new Error(`当前状态${currentState}不支持事件${event}`);
      }
      // 执行当前状态的退出行为
      if (typeof stateRule.onExit === 'function') {
        stateRule.onExit();
      }
      // 切换到下一个状态
      currentState = nextState;
      // 执行下一个状态的进入行为
      const nextStateRule = stateConfig[currentState];
      if (typeof nextStateRule.onEnter === 'function') {
        nextStateRule.onEnter();
      }
      return currentState;
    },
    // 获取当前状态
    getState() {
      return currentState;
    }
  };
}

// 定义灯光状态配置
const lightStateConfig = {
  '关闭': {
    transitions: {
      '按开关': '低亮'
    },
    onExit() {
      console.log('灯光关闭状态退出');
    },
    onEnter() {
      console.log('灯光已关闭,亮度0%');
    }
  },
  '低亮': {
    transitions: {
      '按开关': '高亮'
    },
    onExit() {
      console.log('灯光低亮状态退出');
    },
    onEnter() {
      console.log('灯光低亮,亮度50%');
    }
  },
  '高亮': {
    transitions: {
      '按开关': '关闭'
    },
    onExit() {
      console.log('灯光高亮状态退出');
    },
    onEnter() {
      console.log('灯光高亮,亮度100%');
    }
  }
};

// 创建灯光状态机实例
const lightMachine = createLightStateMachine('关闭', lightStateConfig);

// 测试状态切换
console.log(lightMachine.getState()); // 输出 关闭
lightMachine.trigger('按开关'); // 输出 灯光关闭状态退出 灯光低亮,亮度50%
console.log(lightMachine.getState()); // 输出 低亮
lightMachine.trigger('按开关'); // 输出 灯光低亮状态退出 灯光高亮,亮度100%
console.log(lightMachine.getState()); // 输出 高亮
lightMachine.trigger('按开关'); // 输出 灯光高亮状态退出 灯光已关闭,亮度0%
console.log(lightMachine.getState()); // 输出 关闭

实现优势与注意事项

用闭包实现状态机的优势非常明显,首先是封装性好,内部状态和规则都被闭包保护,外部无法直接修改currentState,只能通过暴露的trigger和getState方法操作,避免状态混乱。其次是无额外依赖,不需要引入第三方状态管理库,代码轻量,适合简单场景的状态管理。

需要注意的点是,如果状态机的状态非常多,状态配置会变得冗长,这时候可以考虑把状态配置抽成独立文件维护。另外闭包保存的变量会一直存在内存中,如果状态机实例不再使用,需要及时解除引用,避免内存泄漏。

适用场景

这种实现方式适合状态数量不多、逻辑相对简单的场景,比如前端的按钮交互状态、表单步骤流转、简单的游戏角色状态控制,还有后端的简单业务流程状态管理等。如果状态逻辑非常复杂,也可以基于这个思路扩展,加入状态历史记录、异步状态转移等能力。

javascript闭包状态机函数式编程修改时间:2026-07-12 12:42:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。