闭包实现带历史记录的命令行工具,核心是将history数组和currentposition封装在立即执行函数内,对外暴露execute、getprevious、getnext、gethistory四个接口,确保数据私有、避免全局污染。

用闭包实现带历史记录的命令行工具,核心是把命令历史、当前状态封装在闭包内,对外只暴露执行和查询接口,避免全局污染,同时保持数据私有性和持久性。
闭包封装历史与执行逻辑
定义一个立即执行函数,内部维护 history 数组 和可选的 currentPosition(用于上下键翻历史),返回一组操作函数:
- execute(cmd):保存命令到 history(去重或允许重复按需),执行它,并重置位置(为后续翻历史做准备)
- getHistory():返回历史副本(不暴露原始数组,防误改)
- getPrevious():从当前位置往前取一条(模拟 ↑ 键)
- getNext():从当前位置往后取一条(模拟 ↓ 键)
基础实现示例
下面是一个轻量可用的闭包结构:
const createCLI = () => {
const history = [];
let currentPosition = -1; // -1 表示未开始翻历史
<p>const execute = (cmd) => {
if (cmd.trim() === '') return;
history.push(cmd.trim());
currentPosition = history.length; // 执行后指向末尾之后,下次翻历史从倒数第一条开始
};</p><p>const getPrevious = () => {
if (history.length === 0) return '';
if (currentPosition </p><p>const getNext = () => {
if (history.length === 0 || currentPosition >= history.length - 1) return '';
currentPosition++;
return history[currentPosition] || '';
};</p><p>const getHistory = () => [...history]; // 返回拷贝</p><p>return { execute, getPrevious, getNext, getHistory };
};</p><p>// 使用
const cli = createCLI();
cli.execute('ls');
cli.execute('cd /home');
console.log(cli.getPrevious()); // 'cd /home'
console.log(cli.getPrevious()); // 'ls'
console.log(cli.getNext()); // 'cd /home'</p>对接真实输入场景(如 input 元素)
实际中常配合 input 或 textarea + 键盘事件。关键点:
- 监听
keydown,对 ArrowUp 调用getPrevious()并填入输入框 - 对 ArrowDown 调用
getNext() - 回车时调用
execute(input.value),并清空输入框 - 注意:翻历史时需暂存用户已输入但未执行的内容(称“临时输入”),避免被覆盖 —— 可在闭包内加一个
tempInput字段,在首次按 ↑ 时备份当前值
增强实用性的小技巧
让工具更贴近真实 CLI 体验:
- 限制历史长度(如最多保留 100 条),插入前用
history.shift()腾出空间 - 支持模糊搜索历史(如
search(query)返回匹配项数组),用history.filter(cmd => cmd.includes(query)) - 导出/导入历史:提供
exportJSON()(JSON.stringify(history))和importJSON(str) - 命令执行结果不放在闭包里 —— 那是使用者的业务逻辑,闭包只管“记什么、翻什么”,执行交给外部回调(如
execute(cmd, runHandler))
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











