报错e is undefined 递归事件处理函数的正确语法是什么?
错误原因
- 你在
keydown事件回调末尾主动调用了checkExit(),没有传入事件参数,所以函数执行时形参e为undefined,触发报错 - 递归调用逻辑完全错误:键盘事件是浏览器触发的,不需要你主动循环调用回调函数,每次按键时浏览器会自动把事件对象作为参数传入回调执行
- 额外问题:
prevKeyCode变量没有提前声明,会默认挂到全局作用域,容易产生冲突;每次点击按钮激活时都会重复绑定keydown事件,会导致内存泄漏和逻辑异常
修正后的实现代码
// 把状态变量提到外部,避免每次点击重新初始化 let prevKeyCode = null; // 提前定义退出检测函数 function exit(event) { const code = event.keyCode || event.which; const doubleEnter = (code == 13 && prevKeyCode == code); if (event.type == "click") { return true; } else if (event.type == 'keydown') { if (code == 27 || doubleEnter) { prevKeyCode = null; return true; } else if (code == 13) { prevKeyCode = 13; } else { prevKeyCode = code; } return false; } return false; } $("button#ul").on("click", function(event) { const button = $(this); button.toggleClass("active"); // 先解绑之前可能存在的keydown事件,避免重复绑定 $(document).off("keydown", handleKeydown); if (button.hasClass('active')) { // 绑定键盘事件 $(document).on("keydown", handleKeydown); } // 键盘事件回调单独定义,方便绑定和解绑 function handleKeydown(e) { if (exit(e) == true) { button.removeClass('active'); $(document).off("keydown", handleKeydown); } } });
改动说明
- 移除了错误的主动递归调用逻辑,完全依靠浏览器事件触发执行回调
- 提前声明
prevKeyCode状态变量,避免隐式全局变量问题 - 每次绑定
keydown事件前先解绑旧事件,避免重复绑定导致的多次执行问题 - 把键盘事件回调单独命名定义,方便精准解绑,避免误解绑其他同类型事件
内容的提问来源于stack exchange,提问作者the_indios
相关产品推荐
相关产品推荐

