Vanilla JS石头剪刀布项目随机出现Uncaught TypeError报错如何解决
问题原因与解决方案
根因分析
你遇到的随机报错有两个核心诱因:
- 事件目标获取错误:你给
.tool元素绑定了点击事件,但点击SVG图标时,e.target可能命中SVG内部的子元素(比如<path>、<g>标签),这些子元素没有设置id属性,导致mapChoices[e.target.id]返回undefined,传入logic函数后访问arrayMatrix[undefined]自然会抛出错误。报错概率随机的原因就是你有时候点到了外层带id的.tool容器,有时候点到了内部无id的SVG子元素。 - 隐式全局变量污染:
randomizer函数里的randomDecimal、randomChoice没有加let/const声明,会自动变成全局变量,多次触发点击时可能出现变量值被意外覆盖的问题。
修复方法
- 替换事件目标获取方式:将
doRound函数里的e.target替换为e.currentTarget,e.currentTarget永远指向绑定事件的元素本身,不会随点击位置变化:
function doRound(e){ // 替换e.target为e.currentTarget let humanChoice = mapChoices[e.currentTarget.id] let randomChoice = randomizer(); let result = logic(humanChoice, randomChoice); console.log("doround result: " + result); return result; }
- 补全变量声明:给
randomizer函数里的局部变量加上let声明:
function randomizer() { let choices = ["rock", "paper", "scissor"]; // 补全let声明 let randomDecimal = Math.random(); let randomChoice = Math.floor(randomDecimal*3); let computerChoice = choices[randomChoice]; console.log(computerChoice); return randomChoice; }
通用优化建议
- 所有变量都必须加
let/const声明,避免生成隐式全局变量,也可以在代码顶部加上'use strict'开启严格模式,这类错误会直接抛出提示,方便排查。 - 可以给
humanChoice增加兜底判断,避免异常值传入逻辑函数:
let humanChoice = mapChoices[e.currentTarget.id] if (humanChoice === undefined) return
- 目前你用JS实现的鼠标悬浮加
selected类的效果,可以直接用CSS的:hover伪类实现,不需要JS绑定事件,性能更好,代码也更简洁。 - 代码里的命名可以更规范,比如
randomizer可以改成getComputerChoice,语义更清晰,后续维护更方便。
内容的提问来源于stack exchange,提问作者SirBecalo
相关产品推荐
相关产品推荐

