求助:JavaScript中向对象属性数组添加值时出现Uncaught TypeError错误的解决方法
问题排查与解决方案
咱们先拆解你遇到的两个核心问题,一步步解决:
1. 报错的直接原因:this 指向错误
你在addEventListener的回调里写this.choosenAnsers.push(chosenAns)时,这里的this并不是指向questions对象——在普通函数的事件回调中,this默认绑定到触发事件的DOM节点(也就是你点击的<input>单选框)。而单选框元素根本没有choosenAnsers属性,自然会抛出Cannot read properties of undefined (reading 'push')的错误。
修复方案(二选一即可):
- 方案一:用箭头函数绑定外层
this
箭头函数不会创建自己的this,它会继承外层作用域(也就是getAns方法)的this,这样就能正确指向questions对象:getAns(Option) { Option.forEach((opt1) => { // 改成箭头函数 opt1.addEventListener('click', (e) => { // 这里也改成箭头函数 const chosenAns = e.target.value; this.choosenAnsers.push(chosenAns); }); }); } - 方案二:提前保存
this的引用
在forEach外层先把questions对象的this存到变量里,比如self,之后在回调里用self访问:getAns(Option) { const self = this; // 保存当前this指向(即questions对象) Option.forEach(function (opt1) { opt1.addEventListener('click', function (e) { const chosenAns = e.target.value; self.choosenAnsers.push(chosenAns); // 用self代替this }); }); }
2. 隐藏的逻辑问题:对象属性重复覆盖
你定义的questions对象里多次重复写correctAns属性:
const questions = { question1: Question1, correctAns: 'javaScript', // 会被后面的覆盖 question2: Question2, correctAns: 'CSS', // 覆盖上一个correctAns question3: Question3, correctAns: 'Python', // 继续覆盖 question4: Question4, correctAns: 'Html', // 最终只有这个值生效 // ... };
在JavaScript对象中,重复的属性名会被最后一次定义的值覆盖,所以你的questions.correctAns最终只会是'Html',前面三个题的正确选项全丢了——这会导致后续判断答案对错完全失效。
优化方案:重构对象结构
把questions改成问题数组,每个元素是一个独立的问题对象,包含题目、正确答案等信息,逻辑更清晰,也不会出现属性覆盖:
const questions = { allQuestions: [ { question: Question1, correctAns: 'javaScript' }, { question: Question2, correctAns: 'CSS' }, { question: Question3, correctAns: 'Python' }, { question: Question4, correctAns: 'Html' } ], choosenAnsers: [], // ... 其他方法 };
最终完整修复代码
const Question1 = document.querySelector('.qestion1').textContent; const Option1 = document.querySelectorAll('input[name="option1"]'); const Question2 = document.querySelector('.qestion2').textContent; const Option2 = document.querySelectorAll('input[name="option2"]'); const Question3 = document.querySelector('.qestion3').textContent; const Option3 = document.querySelectorAll('input[name="option3"]'); const Question4 = document.querySelector('.qestion4').textContent; const Option4 = document.querySelectorAll('input[name="option4"]'); const btn = document.querySelector('.btn'); const questions = { allQuestions: [ { question: Question1, correctAns: 'javaScript' }, { question: Question2, correctAns: 'CSS' }, { question: Question3, correctAns: 'Python' }, { question: Question4, correctAns: 'Html' } ], choosenAnsers: [], getAns(Option) { Option.forEach((opt1) => { opt1.addEventListener('click', (e) => { const chosenAns = e.target.value; this.choosenAnsers.push(chosenAns); console.log('已选择的答案:', this.choosenAnsers); // 可以验证是否成功添加 }); }); }, }; console.log(questions.allQuestions[0].question); questions.getAns(Option1); questions.getAns(Option2); // 记得给其他选项也绑定监听 questions.getAns(Option3); questions.getAns(Option4);
这样修改后,点击单选框就能正确把选中值添加到choosenAnsers数组,同时也修复了正确答案被覆盖的隐患。
内容的提问来源于stack exchange,提问作者williams
相关产品推荐
相关产品推荐

