JSHint报循环内函数引用外层变量错误,如何正确绑定事件监听器?
问题原因
JSHint抛出的告警是保守提示,你原本的代码中使用let声明循环变量i和btn_id,利用块级作用域已经规避了变量共享的问题,代码本身可以正常运行。如果要消除告警,只需要将循环内的函数抽离到外部,通过参数传递或者事件对象获取所需的元素和属性即可,不需要依赖循环内的临时变量。
优化方案(推荐)
利用事件对象的currentTarget属性获取触发事件的元素,不需要额外传递参数,代码更简洁易维护:
第一步:修改抽离后的处理函数
function getButtonData(event) { // currentTarget对应你绑定事件的元素:buttons[i].childNodes[1] const clickPart = event.currentTarget; // 父元素就是class为btn的按钮本身 const targetBtn = clickPart.parentElement; // 直接读取已经设置到按钮上的ID,不需要依赖外部变量 clickedButtonID = targetBtn.id; clickedButtonTitle = clickPart.childNodes[1].innerHTML; clickedButtonColour = targetBtn.getAttribute("class").split(" ")[1]; console.log("The ID of the clicked button is: ", clickedButtonID, "\n", 'The colour of the clicked button is ', clickedButtonColour); if (firstClick === 1) { firstClick = 0; window.addEventListener("resize", positionHabitCard); // 注意:DOMContentLoaded在页面加载完成后就已触发,此处绑定不会生效,直接调用即可 positionHabitCard(); } }
第二步:修改循环内的绑定逻辑
function addListenersToAllBtns() { for (let i = 0; i < buttons.length; i++) { let btn_id = guidGenerator(); buttonIDs[i] = btn_id; buttons[i].setAttribute("id", btn_id); // 直接传入抽离的函数即可 buttons[i].childNodes[1].addEventListener("click", getButtonData); buttons[i].childNodes[1].addEventListener("click", showHabitCard); } }
备选方案:bind预置参数
如果你不想通过元素层级获取属性,可以用bind方法提前将btn_id和当前按钮元素传入处理函数:
// 处理函数接收预置的参数 function getButtonData(btn_id, targetBtn, event) { clickedButtonID = btn_id; clickedButtonTitle = targetBtn.childNodes[1].childNodes[1].innerHTML; clickedButtonColour = targetBtn.getAttribute("class").split(" ")[1]; console.log("The ID of the clicked button is: ", clickedButtonID, "\n", 'The colour of the clicked button is ', clickedButtonColour); if (firstClick === 1) { firstClick = 0; window.addEventListener("resize", positionHabitCard); positionHabitCard(); } } // 循环内绑定逻辑 buttons[i].childNodes[1].addEventListener("click", getButtonData.bind(null, btn_id, buttons[i]));
内容的提问来源于stack exchange,提问作者seklerek
相关产品推荐
相关产品推荐

