JavaScript类方法中while循环失效,RedoAll功能实现遇阻
问题:实现redoAll方法时的代码错误分析
题目要求
Redo All
假设我们要重做所有已撤销的操作,只需持续执行redo操作直到不得不停止。何时停止?当undos栈为空时停止!记得我们的栈类中有一个用于判断栈是否为空的同名方法。
目标:实现Redo All
请实现redoAll方法,持续执行redo操作直到没有更多可撤销的操作。
我的代码
Stack类
const { MAX_STACK_SIZE } = require('./config'); class Stack { constructor() { this.items = []; } push(item) { if (MAX_STACK_SIZE > this.items.length) { this.items.push(item) } else throw new Error("Error"); } pop() { if (this.items.length === 0) { throw new Error("Error") } return this.items.pop(); } isEmpty() { if (this.items.length === 0) return true; return false; } peek() { return this.items[this.items.length - 1] } } module.exports = Stack;
OperationManager类
const Stack = require('./Stack'); class OperationManager { constructor() { this.operations = new Stack(); this.undos = new Stack(); } addOperation(operation) { this.operations.push(operation); } undo() { this.undos.push(this.operations.pop()) } redo() { this.operations.push(this.undos.pop()) } redoAll() { while (true) { if (this.undos.length != 0) { this.operations.push(this.undos.pop()) } else false; } } } module.exports = OperationManager;
尝试过的错误写法
我曾误以为this.undos是数组,尝试用for...of循环遍历,代码如下:
for(i of this.undos) { if(this.undos.length != 0) { this.operations.push(i)&&this.undos.pop(i) } }
运行时提示错误:
this.undos is not iterable.
错误原因及修正方案
核心问题点
- 错误访问栈的长度:
Stack类的数组存在items属性中,但你直接用this.undos.length——this.undos是Stack实例,本身没有length属性,正确做法是调用Stack类提供的isEmpty()方法判断栈是否为空。 - 无限循环无法终止:
while(true)循环里,栈为空时仅返回false,没有终止循环的逻辑,会导致死循环。 for...of使用错误:自定义Stack类未实现迭代器接口,不能直接用for...of遍历。栈遵循后进先出规则,需用循环结合isEmpty()和pop()处理才符合设计逻辑。pop()方法误用:Stack类的pop()不需要传参数,this.undos.pop(i)是错误写法,pop()本身会移除并返回栈顶元素。
修正后的redoAll方法
复用已有的redo()方法更简洁,避免重复代码:
redoAll() { // 只要undos栈不为空,就执行redo操作 while (!this.undos.isEmpty()) { this.redo(); } }
也可以直接写逻辑:
redoAll() { while (!this.undos.isEmpty()) { this.operations.push(this.undos.pop()); } }
额外优化点
undo()和redo()方法未处理栈为空的情况——比如operations栈为空时调用undo(),会触发pop()里的错误;同理undos为空时调用redo()也会报错。可添加判断避免抛出错误:
undo() { if (!this.operations.isEmpty()) { this.undos.push(this.operations.pop()); } } redo() { if (!this.undos.isEmpty()) { this.operations.push(this.undos.pop()); } }
内容的提问来源于stack exchange,提问作者Matteo V
相关产品推荐
相关产品推荐

