JS中点击按钮触发Cannot read property 'saidOrNot' of undefined报错的修复
特朗普言论判断小游戏JS交互报错修复
报错核心根因
控制台抛出的Uncaught TypeError: Cannot read property 'saidOrNot' of undefined,本质是三处逻辑写错导致的:
- splice数组删除逻辑完全误用
原代码中调用statements.splice(statementInd)时只传了1个参数,按照JS原生方法规则,这种写法会把从当前选中下标开始、直到数组末尾的所有元素全部删除,并非只删掉当前展示的这一条语句。第一次点击按钮时就会把大半个语句列表清空,后续生成的随机索引很容易超出数组现有长度,取到不存在的undefined对象,自然读不到它的saidOrNot属性触发报错。
尝试修改的statements = statements.splice(statementInd, 1)写法也是错的:splice是原地修改原数组的方法,它的返回值是「被删掉的元素组成的新数组」,把这个返回值赋值给statements变量,会直接把原本存储所有剩余语句的数组覆盖成刚删掉的那1条元素,数组长度骤减,进一步放大取值越界的问题。 - 按钮交互逻辑无区分
原代码里“是”“否”两个按钮的点击判断逻辑完全一致,都是判断当前语句的saidOrNot为true就进入答对流程,两个按钮功能完全重复,没有对应点击选择的判断分支,本身就不符合游戏的交互逻辑。 - 数组空值无兜底
当所有10条语句都完成作答后,statements数组长度变为0,没有做边界判断就直接随机取元素,也会因为取到undefined触发报错。
具体修复方案
1. 修正splice单条删除逻辑
要只删掉当前展示的那一条语句,正确的写法是给splice传两个参数:statements.splice(statementInd, 1)
其中第二个参数1代表仅删除指定下标的1个元素;因为splice会直接修改原数组,不需要把方法的返回值重新赋值给statements,否则会覆盖掉剩余的语句列表。
2. 拆分两个按钮的判断分支
让点击行为和判断逻辑对应:
- 点击“是(特朗普确实说过这句话)”按钮时:如果当前语句的
saidOrNot === true,进入答对流程;否则进入答错流程 - 点击“否(特朗普没说过这句话)”按钮时:如果当前语句的
saidOrNot === false,进入答对流程;否则进入答错流程
3. 增加数组边界兜底
当statements.length === 0时,停止加载新的随机语句,直接展示最终答题得分,避免取值时碰到undefined。
修复后核心代码参考
function right(statementInd) { // 仅删除当前选中的1条语句 statements.splice(statementInd, 1); // 数组空了就不再加载新题,展示最终结果 if (statements.length === 0) { scoreBoard_p.innerHTML = `答题完成,最终得分:${score}/10`; return; } statementIndex = Math.floor(Math.random() * statements.length); trumpStatements_p.innerHTML = statements[statementIndex].statement; score++; scoreBoard_p.innerHTML = `You have got ${score}/10 correct`; // 原有答对后的动画逻辑保持不变 document.getElementsByTagName("body")[0].classList.add("right"); setTimeout(function() { document.getElementsByTagName("body")[0].classList.remove("right"); }, 400); } // “是”按钮的判断逻辑保持正确选项匹配 yes_btn.addEventListener("click", function() { if (statements[statementIndex].saidOrNot === true) { right(statementIndex); } else { wrong(statementIndex); } }); // “否”按钮绑定相反的判断逻辑,匹配“没说过”的选项 no_btn.addEventListener("click", function() { if (statements[statementIndex].saidOrNot === false) { right(statementIndex); } else { wrong(statementIndex); } });
注:
wrong函数内的splice逻辑和right函数保持一致,替换为单条删除的正确写法即可,原有动画、音效逻辑无需改动。
内容的提问来源于stack exchange,提问作者Add it yeah
相关产品推荐
相关产品推荐

