Generator函数天然适合实现带状态恢复的计算器逻辑,因其能暂停执行、保存完整计算上下文(如累加值、上一步操作、运算符等),并通过next()精确恢复执行;示例封装了add、subtract、clear、undo操作,结合class可提升实用性与接口直观性。

Generator 函数天然适合实现带状态恢复的计算器逻辑,因为它能暂停执行、保存内部状态(包括局部变量、执行位置、调用栈等),并在下次调用 next() 时从中断处继续。
用 Generator 封装计算器状态
把加减乘除、清空、撤销等操作封装成一个可中断、可恢复的流程。关键不是“存数字”,而是“存整个计算上下文”——比如当前累加值、上一步操作、待处理的运算符等。
示例:一个支持 add、subtract、clear 和 undo 的简易计算器 Generator:
function* calculator() {
let result = 0;
let history = [0]; // 初始状态快照
let lastOp = null;
<p>while (true) {
const { type, value } = yield result;</p><pre class="brush:php;toolbar:false;">switch (type) {
case 'add':
result += value;
history.push(result);
lastOp = 'add';
break;
case 'subtract':
result -= value;
history.push(result);
lastOp = 'subtract';
break;
case 'clear':
result = 0;
history = [0];
lastOp = 'clear';
break;
case 'undo':
if (history.length > 1) {
history.pop();
result = history[history.length - 1];
}
break;
default:
// 忽略未知指令
}} }
用 next() 驱动并恢复状态
Generator 实例本身即状态载体。每次调用 next() 传入操作指令,它就恢复执行、更新内部变量、返回当前结果——无需额外管理 state 对象。
- 创建一次 generator 实例:
const calc = calculator(); - 首次调用
calc.next()启动并返回初始值{ value: 0, done: false } - 后续调用
calc.next({ type: 'add', value: 5 })恢复执行,应用操作,返回新结果 - 即使中间隔了很久、甚至跨函数调用,只要持有
calc引用,状态就一直保留
配合闭包或类增强实用性
纯 Generator 已具备状态恢复能力,但实际项目中常结合 class 封装接口,让使用者更直观:
class StatefulCalculator {
#gen;
#lastResult;
<p>constructor() {
this.#gen = calculator();
this.#lastResult = this.#gen.next().value; // 初始化
}</p><p>add(n) {
this.#lastResult = this.#gen.next({ type: 'add', value: n }).value;
return this;
}</p><p>subtract(n) {
this.#lastResult = this.#gen.next({ type: 'subtract', value: n }).value;
return this;
}</p><p>clear() {
this.#lastResult = this.#gen.next({ type: 'clear' }).value;
return this;
}</p><p>undo() {
this.#lastResult = this.#gen.next({ type: 'undo' }).value;
return this;
}</p><p>value() {
return this.#lastResult;
}
}</p><p>// 使用:
const calc = new StatefulCalculator();
console.log(calc.add(10).subtract(3).value()); // 7
console.log(calc.undo().value()); // 10</p>
注意边界与可预测性
Generator 的状态恢复是精确的,但需注意几点:
- 不能在 yield 外部修改内部变量(如直接改
result),否则破坏一致性 - 如果需要持久化(如刷新页面后恢复),得把
history和lastOp序列化存 localStorage,再手动重建 generator 状态(Generator 本身不可序列化) - 避免在 generator 内做异步操作(如 await),除非用
async function*—— 但此时状态恢复逻辑需配合 Promise 生命周期
Generator 不是万能状态机,但它让“暂停-恢复-延续”变得极其自然。计算器这类线性、步骤明确、依赖历史的操作,正是它的理想用武之地。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











