闭包在undo/redo中用于封装保护历史栈状态并提供安全接口;通过函数作用域隐藏history、redostack和index,仅暴露push/undo/redo等方法,确保深拷贝快照、步数限制与边界控制逻辑内聚统一。

闭包在 Undo/Redo 功能中主要用来**封装和保护历史栈状态**,同时提供安全、可控的操作接口。它不直接“实现”撤销重做逻辑,而是让 undo、redo、push 等方法能访问并修改私有栈(如 history 和 redoStack),又不暴露内部数据,避免外部误操作。
用闭包隔离历史栈,防止外部篡改
把 history、redoStack 和当前指针 index 声明在函数作用域内,只通过返回的对象方法操作它们:
- 外部无法直接读写
history数组,只能调用push()记录新状态 -
undo()和redo()内部可安全移动index、截取数组、维护redoStack,无需担心竞态或越界 - 每个编辑器实例可独立拥有自己的闭包环境,互不影响
闭包配合快照(snapshot)保存可恢复状态
每次 push() 时,闭包内部应深拷贝当前数据(如对象、数组),而不是存引用:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 推荐用
JSON.parse(JSON.stringify(state))(简单结构)或structuredClone()(现代环境) - 若状态含函数、Date、RegExp 等,需自定义序列化逻辑,否则闭包保存的快照会失效
- 闭包确保每次
undo()恢复的是当时精确的副本,不是被后续修改污染的引用
支持撤销步数限制与自动清理
闭包内可内置容量控制逻辑,比如最多保留 50 步:
-
push()时检查history.length > maxSteps,自动shift()最老项 - 执行
undo()后再push()新状态,应清空redoStack—— 这个规则由闭包统一维护,调用方无需关心 - 所有边界判断(如
index === 0时禁用undo)都在闭包方法里完成,对外返回布尔值或静默处理
实际使用示例(精简版)
下面是一个带闭包的 UndoManager 工厂函数:
function createUndoManager(maxSteps = 50) {
let history = [];
let redoStack = [];
let index = -1;
return {
push(state) {
// 截断 redo 栈,插入新状态
history = history.slice(0, index + 1);
history.push(structuredClone(state));
index++;
if (history.length > maxSteps) {
history.shift();
index--;
}
redoStack = [];
},
undo() {
if (index 0; },
canRedo() { return redoStack.length > 0; }
};
}
// 使用
const editorUndo = createUndoManager(30);
editorUndo.push({ text: "Hello" });
editorUndo.push({ text: "Hello World" });
editorUndo.undo(); // → { text: "Hello" }
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










