JavaScript 组合快捷键实战:基于 keydown/keyup 与 event.code 实现 runOnKeys 多键热键
文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载导读本文围绕 Modern JavaScript Tutorial本项目 javascript.info键盘事件章节中的一道经典编程练习「Extended hotkeys」展开编写一个runOnKeys(func, code1, code2, ..., code_n)函数当用户同时按下若干指定物理按键时执行回调。文章完整还原了任务要求与官方解法并结合 键盘事件章节 的event.code/event.key原理与仓库内可运行的示例页面深入讲解多键组合热键的实现机制、粘滞键sticky key陷阱与移动端边界情况读者学完后可直接在任意页面中复刻这一热键工具函数。任务背景Extended hotkeys该任务位于 2-check-sync-keydown/task.md是「Keyboard: keydown and keyup」章节的课后编程题任务标注的重要性为 5满分 5属于该章节核心难点的实战检验。任务要求创建一个函数runOnKeys(func, code1, code2, ... code_n)其行为是当用户同时按下键码为code1、code2……code_n的按键时执行func。任务给出的使用示例无论当前输入法语言、无论是否开启大写锁定只要同时按下Q和W两个键就弹出alert(Hello!)runOnKeys( () alert(Hello!), KeyQ, KeyW );注意示例中传入的KeyQ、KeyW并不是字符而是event.code形式的物理键码——这正是任务想训练的核心知识点用event.code而不是event.key来绑定热键才能保证热键在语言切换、大小写切换后依然稳定生效。前置原理keydown / keyup 与 event.code两个事件的分工按章节 article.md 所述keydown—— 按键被按下时触发若长按不松会因系统自动重复auto-repeat连续触发多次keyup—— 按键被松开时触发正常情况下一次按压只对应一次keyup。因此一个完整按键周期的典型事件序列是多个keydown长按自动重复 一个keyup。对于长按自动重复产生的事件事件对象上的event.repeat属性为true可用于识别重复触发。event.key 与 event.code 的区别按键event.keyevent.codeZz小写KeyZShiftZZ大写KeyZevent.key是语义字符随语言、大小写、输入法变化event.code是物理键码由按键在键盘上的物理位置决定始终不变。例如左右两个Shift键event.key都是Shift而event.code分别是ShiftLeft与ShiftRight能精确区分按的是哪一颗物理键。键码的命名规则详见章节中的说明字母键Keyletter如KeyA、KeyB数字键Digitnumber如Digit0、Digit1特殊键直接用名称Enter、Backspace、Tab等。⚠️ 大小写敏感正确的写法是event.code KeyZkeyZ永远不会匹配——Key的首字母必须大写。为什么热键用 event.code章节中给出了一个经典场景——撤销快捷键CtrlZMac 为CmdZdocument.addEventListener(keydown, function(event) { if (event.code KeyZ (event.ctrlKey || event.metaKey)) { alert(Undo!) } });用event.code判断的好处是即便用户在系统中切换了输入语言、同一颗物理键打出不同字符event.code仍指向同一物理键热键始终有效。但event.code也有一个已知陷阱不同键盘布局下同一物理键位可能映射不同字符。以美式 QWERTY 与德式 QWERTZ 布局为例同一颗物理键在美式布局中是Z在德式布局中却是Y字母互换因此德式布局用户按下Y时event.code依然是KeyZevent.code KeyZ的判断会在意想不到的情况下通过。这类键码错位主要发生在少数字母键上如KeyA、KeyQ、KeyZ特殊键如Shift不受影响。结论也是本任务的设计取向热键绑定物理位置用event.code热键绑定语义字符用event.key。本任务要求传入KeyQ、KeyW正是基于前者——无论任何语言、无论是否开大写锁定都生效。官方解题思路双监听 Set 追踪按下状态官方解法记录在 solution.md思路分三步挂两个监听器document.onkeydown与document.onkeyup用集合记录状态创建pressed new Set()保存当前处于按下状态的键码——keydown时把event.code加入集合keyup时删除每次 keydown 时做全量检查遍历runOnKeys传入的所有键码若全部都在pressed集合中说明用户已同时按下所需全部按键此时执行func。这里选择Set而非普通数组是因为判断某个键是否按下可以做到 O(1) 查找并且键码天然具有唯一性与Set的语义完全吻合。完整实现仓库可运行版本逐段拆解任务目录下的 solution.view/index.html 提供了可直接在浏览器打开运行的完整实现下面逐段拆解!DOCTYPE HTML html body pPress Q and W together (can be in any language)./p script function runOnKeys(func, ...codes) { let pressed new Set(); document.addEventListener(keydown, function(event) { pressed.add(event.code); for (let code of codes) { // 检查所需键是否全部按下 if (!pressed.has(code)) { return; } } // 全部按下执行回调…… // 关键细节alert 弹出期间用户松开按键时 // JavaScript 收不到 keyup 事件 // pressed 集合会误以为这些键仍处于按下状态 // 为避免粘滞键这里重置集合 // 若用户想再次触发热键需要把所有键重新按一遍 pressed.clear(); func(); }); document.addEventListener(keyup, function(event) { pressed.delete(event.code); }); } runOnKeys( () alert(Hello!), KeyQ, KeyW ); /script /body /html执行流程以 Q W 组合为例用户操作与内部状态变化如下用户按下Q触发keydownevent.code KeyQ被加入pressed用户按下W触发keydownKeyW被加入pressed随后遍历codes发现KeyQ、KeyW都已存在条件满足调用pressed.clear()清空集合再执行func()弹出Hello!用户松开按键keyup触发event.code从集合中删除此时集合已清空删除操作无副作用。容易被忽略的粘滞键问题官方实现中pressed.clear()一行是整道题的精髓。原因是alert()是阻塞式的模态对话框弹出期间浏览器不再向页面派发后续的keyup事件。若不清空集合用户松开 Q、W 后pressed里依然残留着两个键码下一次随意按下一个键就会再次误触发func()造成热键粘滞。清空集合的代价是用户若想再次触发热键必须把全部按键重新按一遍即使之前一直没松开也不行。这在交互上是可接受的取舍也保证了状态的一致性。函数签名与可复用性runOnKeys(func, ...codes)使用剩余参数接收任意数量的键码因此它天然支持二键、三键乃至更多键的组合runOnKeys(showMenu, KeyA, KeyB, KeyC); // 三键组合 runOnKeys(saveDoc, ControlLeft, KeyS); // 修饰键与普通键组合监听器挂在document上而非某个具体元素使热键在页面全局生效不依赖焦点位置。边界情况与工程化扩展长按自动重复auto-repeat按官方实现长按Q不松会连续触发多个keydown若期间再按下Wfunc可能被连续执行多次。若希望只在按下组合的第一次触发可利用章节中提到的event.repeat过滤document.addEventListener(keydown, function(event) { if (event.repeat) return; // 忽略自动重复产生的 keydown pressed.add(event.code); // ……后续检查逻辑 });移动端与虚拟键盘IME章节的「Mobile Keyboards」一节明确指出按 W3C 标准IME输入法编辑器触发的键盘事件中e.keyCode应为229、e.key应为Unidentified。虽然部分虚拟键盘在按方向键、退格键时仍会给出正确的key/code但并没有任何保证——因此依赖keydown/keyup的热键逻辑在移动端可能失效。若热键面向移动端用户需要补充触摸/点击等替代触发路径。组合键判定注意修饰键不要用 keydown 计数本任务的同时按下基于键码集合判断天然兼容Ctrl、Shift等修饰键。但注意修饰键应作为普通键码传入如ControlLeft或改用event.ctrlKey、event.metaKey、event.altKey、event.shiftKey布尔属性直接判断避免单独为修饰键维护按下状态带来额外的状态同步成本。与 input 事件的分工章节开篇强调键盘事件只应处理真正的键盘操作热键、特殊键不应用来跟踪输入框内容。文本输入可能来自粘贴、语音识别、自动填充等多种途径跟踪input内容变化应使用input/change事件见 events-change-input 章节。本任务属于键盘操作范畴使用keydown/keyup是正确选择。验证与调试工具章节配套提供了键码调试台 keyboard-dump.view/index.html在文本框内按键页面会实时输出每次事件的类型、key、code、修饰键状态与repeat标记还可用复选框对keydown/keyup执行忽略或阻止默认行为其逻辑见 keyboard-dump.view/script.js。验证runOnKeys时的建议步骤打开 solution.view/index.html同时按下Q与W确认弹出Hello!在alert弹出时松开按键确认关闭对话框后再按任意单键不会重复触发粘滞键已被清除切换到其他输入语言或开启大写锁定重复步骤 2确认热键依然生效验证event.code的布局无关性只按其中一个键确认不会触发。小结组合热键的实现模型是keydown 加入集合 keyup 移出集合 全量键码比对状态容器用Set键码应使用event.code物理键码热键才能在语言切换、大小写切换后保持稳定若需要绑定具体字符则改用event.key两者取舍详见 键盘事件章节阻塞式对话框如alert会吞掉keyup触发前必须清空集合防止粘滞键长按自动重复可用event.repeat过滤移动端虚拟键盘的键码不可靠需要额外降级方案完整可运行示例见 solution.view/index.html官方解题说明见 solution.md。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐Modern JavaScript 键盘事件实战指南keydown、keyup、event.key 与 event.code 的正确取舍Modern JavaScript 键盘事件实战指南keydown、keyup、event.key 与 event.code 的正确取舍 本篇指南聚焦 Mod文档/教程前端react-sortable-hoc键盘事件处理keydown与keyupreact sortable hoc键盘事件处理keydown与keyup 你是否在使用react sortable hoc时遇到过键盘操作无效的问题是否想前端UI组件如何快速掌握FossFLOW热键ToolMenu组件中的快捷键提示实现全解析如何快速掌握FossFLOW热键ToolMenu组件中的快捷键提示实现全解析 FossFLOW作为一款强大的开源流程图工具其高效的热键系统能显著提升用户操作前端图形学上一篇用 LayoutLMv3 给扫描病历做信息抽取的完整实战指南下一篇如何用Pixelle-Video实现AI全自动短视频创作告别剪辑烦恼一键生成专业内容创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Context-Engineering 工具集成推理指南:Function Calling 基础、Schema 设计与编排实战

Context-Engineering 工具集成推理指南:Function Calling 基础、Schema 设计与编排实战

文档教程知识库人工智能提示工程 【免费下载链接】Context-Engineering "Context engineering is the delicate art and science of filling the context window with just the right information for the next step." — Andrej Karpathy. A frontier, first-princi…

2026/10/7 9:53:36 阅读更多 →
oneTBB 已知限制全解析:SYCL 调试冲突、静态链接风险与 fork() 等八类边界场景规避指南

oneTBB 已知限制全解析:SYCL 调试冲突、静态链接风险与 fork() 等八类边界场景规避指南

并发编程高性能计算 【免费下载链接】oneTBB oneAPI Threading Building Blocks (oneTBB) 项目地址: https://gitcode.com/gh_mirrors/on/oneTBB 点击查看 免费下载 oneAPI Threading Building Blocks(oneTBB)是一套面向多核硬件的并行编程库…

2026/10/7 9:53:36 阅读更多 →
OpenClaw是什么?AI从“对话”到“行动”的革命

OpenClaw是什么?AI从“对话”到“行动”的革命

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:52:36 阅读更多 →

最新新闻

TCP可靠性机制深度解析:三次握手、重传机制与拥塞控制

TCP可靠性机制深度解析:三次握手、重传机制与拥塞控制

1. TCP到底在解决什么问题 1.1 不要把TCP想象成"一条管子" 很多人学TCP时有个非常顽固的误解:觉得TCP就是一根管子,数据从一头灌进去,另一头按顺序流出来。这个认知会阻碍你理解TCP几乎所有的重要机制,包括三次握手、滑…

2026/10/7 10:29:08 阅读更多 →
山东起酥机源头生产厂家合作实力参考,广受好评值得信赖

山东起酥机源头生产厂家合作实力参考,广受好评值得信赖

先搞懂商用起酥机的核心逻辑:从原理到选型的正确认知 对于烘焙、面点加工从业者来说,起酥机是提升产能、稳定出品的核心设备之一。但很多新手容易陷入一个误区:以为只要买到机器就能直接用,其实起酥机的核心价值,在于贴…

2026/10/7 10:29:08 阅读更多 →
告别套壳与重复适配:2026 开发者主流 LLM 聚合网关选型推荐

告别套壳与重复适配:2026 开发者主流 LLM 聚合网关选型推荐

多数开发者都经历过这样的处境:项目里同时引入 OpenAI、Anthropic、Google 各家 SDK,请求格式互不相同,光适配层就要写几千行代码;想换一个模型或新增一个通道,就得重构、回归测试一遍。维护成本随模型数量线性上涨&am…

2026/10/7 10:29:08 阅读更多 →
AnthropicOpenaiGoogle技术总监级拆解大模型|第10讲 Attention 与 Transformer 到底在算什么?Q、K、V 一次讲明白

AnthropicOpenaiGoogle技术总监级拆解大模型|第10讲 Attention 与 Transformer 到底在算什么?Q、K、V 一次讲明白

AI技术总监级拆解大模型|第10讲 Attention 与 Transformer 到底在算什么?Q、K、V 一次讲明白AI 学习系列|第10讲 / 共26讲 前面第09讲讲了: RNN ↓ LSTM ↓ Seq2Seq ↓ 固定 Context 瓶颈这一讲正式进入今天大模型最核心的计算机制…

2026/10/7 10:29:07 阅读更多 →
芗城区乐米艺术灯饰公司实力公司推荐

芗城区乐米艺术灯饰公司实力公司推荐

选灯避坑与专业服务指南很多业主在装修选灯时都容易陷入认知盲区,比如分不清蓝光危害等级、不了解无主灯的点位逻辑,或是只看图片就下单,收到实物才发现色差、尺寸完全不符。其实照明选购的核心逻辑应该是先看光、再选款,先做设计…

2026/10/7 10:29:07 阅读更多 →
基于Spring Boot+Redis的操作系统日常促学系统设计与实现

基于Spring Boot+Redis的操作系统日常促学系统设计与实现

做了个“操作系统日常促学系统”,可能是最近被课程设计催出来的标准动作。操作系统这门课,知识点又散又抽象,进程管理、内存管理、文件系统、死锁这几块,上课听懂了,隔三天就还回去大半。期末全靠突击,突击…

2026/10/7 10:28:07 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 8:21:32 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 4:21:51 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 1:18:13 阅读更多 →