You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

错误原因及修正方案

核心问题点

  1. 错误访问栈的长度:Stack类的数组存在items属性中,但你直接用this.undos.length——this.undos是Stack实例,本身没有length属性,正确做法是调用Stack类提供的isEmpty()方法判断栈是否为空。
  2. 无限循环无法终止:while(true)循环里,栈为空时仅返回false,没有终止循环的逻辑,会导致死循环。
  3. for...of使用错误:自定义Stack类未实现迭代器接口,不能直接用for...of遍历。栈遵循后进先出规则,需用循环结合isEmpty()和pop()处理才符合设计逻辑。
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 09:24:59