如何移除箭头函数创建的event handler,使游戏达分数上限时按钮失效
解决方案:分数上限后停止按钮累加逻辑
你的问题核心有两个:一是匿名事件回调导致removeEventListener失效,二是游戏结束后没有阻断后续的分数累加流程。下面直接给你修改后的代码和关键说明:
关键修改点
- 抽离命名事件处理函数:把原来的匿名箭头函数改成独立的
handleButtonClick,保留函数引用,方便后续移除监听或做状态判断。 - 游戏状态前置判断:在处理按钮点击时先检查是否已达分数上限,按需决定是否执行加分逻辑。
- 完善结束逻辑:在
endGame中统一处理按钮禁用或事件移除。
修改后的完整代码
// 假设你已定义以下全局变量 let playerScore = 0; let computerScore = 0; const maxScore = 5; // 可自行调整分数上限 const choice = ["rock", "paper", "scissors"]; const gameButtons = document.querySelectorAll(".game-button"); // 替换为你的按钮选择器 // 抽离命名的事件处理函数 function handleButtonClick(e) { // 先判断游戏是否已结束 if (playerScore === maxScore || computerScore === maxScore) { // 按需求:仅更新玩家/CPU选择,不累加分数 const playerSelection = e.target.value; document.querySelector(".player-choice").textContent = `Player Chose: ${playerSelection}`; const computerSelection = getComputerChoice(); document.querySelector(".cpu-choice").textContent = `Computer Chose: ${computerSelection}`; return; // 跳过加分逻辑 } // 游戏未结束,正常执行流程 playerSelection = e.target.value; playGame(); } // 绑定事件 gameButtons.forEach(button => { button.addEventListener("click", handleButtonClick); }); function compare(playerSelection, computerSelection) { if (playerSelection === computerSelection) { // 平局不加分 } else if (playerSelection === "rock" && computerSelection === "scissors") { playerScore++; } else if (playerSelection === "paper" && computerSelection === "rock") { playerScore++; } else if (playerSelection === "scissors" && computerSelection === "paper") { playerScore++; } else { computerScore++; } // 更新分数显示 document.querySelector(".player-score").textContent = `Player score: ${playerScore}`; document.querySelector(".cpu-score").textContent = `CPU score: ${computerScore}`; } function getComputerChoice() { return choice[Math.floor(Math.random() * choice.length)]; } function playGame() { // 更新玩家选择显示 document.querySelector(".player-choice").textContent = `Player Chose: ${playerSelection}`; // 获取并更新CPU选择 const computerSelection = getComputerChoice(); document.querySelector(".cpu-choice").textContent = `Computer Chose: ${computerSelection}`; // 比较结果并更新分数 compare(playerSelection, computerSelection); // 检查是否结束游戏 endGame(); } function endGame() { if (playerScore === maxScore) { console.log("you won"); // 若需彻底禁用按钮,取消下方注释 // gameButtons.forEach(button => { // button.removeEventListener("click", handleButtonClick); // // 或直接禁用按钮:button.disabled = true; // }); } else if (computerScore === maxScore) { console.log("you lost"); // 同上,彻底禁用按钮的逻辑 // gameButtons.forEach(button => { // button.removeEventListener("click", handleButtonClick); // }); } }
原方法无效原因
你之前用匿名箭头函数绑定事件,每次addEventListener都会生成全新的函数实例。removeEventListener需要完全匹配的函数引用才能生效,所以之前的调用等于无效操作。抽离成命名函数后,就能保证绑定和移除的是同一个函数。
如果不需要结束后还显示选择,直接在endGame里移除事件监听或禁用按钮即可,这样点击按钮不会有任何反应。
内容的提问来源于stack exchange,提问作者Moonchkin
相关产品推荐
相关产品推荐

