JavaScript中setInterval内访问words数组返回undefined问题
问题原因
setInterval回调内访问words返回undefined的核心错误是非法数组运算:
words = words - words[wordNo];
JS不支持数组减法操作,执行该行时解释器会将数组强制转为数值类型NaN,原本存储单词列表的数组变量会被直接覆盖为NaN,后续通过索引访问NaN[wordNo]必然返回undefined。
原代码其他逻辑缺陷:
- 随机索引起始值设为1,会漏掉数组第0位单词,且索引边界写死为59,和数组实际长度、剩余单词数不匹配,易触发索引越界
- 切词判断顺序错误,会导致重复切词、计数不准
- 测试结束后未清除定时器,存在无效内存占用
- 倒计时颜色判断存在边界问题,可能出现非最后5秒字体变红的异常
修复方案
- 删除错误的数组减法操作,使用数组
splice方法移除已展示单词,避免重复抽取 - 动态根据当前剩余单词长度生成随机索引,索引从0开始匹配JS数组下标规则
- 调整倒计时执行顺序,倒计时归零时先重置计时时长,再抽取新单词,避免重复触发
- 所有单词展示完成后清除定时器,渲染结束提示
- 修正倒计时颜色判断逻辑,保证仅最后5秒显示红色倒计时
修复后完整JS代码
function startTimer(duration, display) { let wordCount = 0; // 拷贝原单词数组,避免修改全局原始数据 let remainWords = [...words]; let timer = duration; let timerId = null; // 抽词渲染逻辑 const showNextWord = () => { if (remainWords.length === 0) { clearInterval(timerId); const wrapper = document.querySelector('.wrapper'); wrapper.innerHTML = "<div class='text-center fs-3 mt-3 text-danger'>Test Ended</div>"; return; } const randomIdx = Math.floor(Math.random() * remainWords.length); const currentWord = remainWords.splice(randomIdx, 1)[0]; wordCount += 1; word.innerHTML = `<b>${wordCount}. ${currentWord}</b>`; }; // 初始化渲染第一个单词 showNextWord(); timerId = setInterval(function() { timer--; let seconds = parseInt(timer % 60, 10); seconds = seconds < 10 ? "0" + seconds : seconds; display.textContent = seconds; // 倒计时颜色控制 display.style.color = timer <= 5 ? 'red' : 'unset'; // 倒计时归零重置,切换下一个单词 if (timer <= 0) { timer = duration; showNextWord(); } }, 1000); } const words = ["Scene", "Impossible", "Society", "Choose", "Unjust", "Image", "Exam", "Drive", "Internet", "Communication", "Keys", "Murder", "Commit", "Flee", "Practice", "Organize", "Phone", "New", "Agency", "Security", "Since", "Peace", "Fall", "Hi", "Run", "Chase", "Enter", "Industry", "Limit", "Development", "Coach", "Food", "Special", "Biomass", "Release", "Head", "Launch", "Medal", "Play", "Department", "Under", "Curb", "Cooperate", "HIke", "War", "Normal", "Challenge", "Serving", "Bane", "Rapid", "Actress", "obstacles", "Strict", "Forceful", "Citizens", "Team", "Anxious", "Knowledge", "Polite", "Integrity", "Serve", "Loyal", "Equality", "Justice", "Gratitude", "Rare", "Heavy", "Rude", "Explanation", "Pilot", "Pirate", "Ship", "Captain", "Camp", "Rights", "Ragging", "Rust", "Patriotism", "Primary", "Performance", "Pity", "Meeting", "Obedience", "Quick", "Quiet", "Quotes", "Question", "Try", "Unity", "Urge", "Friendship", "Close", "Migrate", "Decline", "Fly", "Highest", "Shall"] const display = document.querySelector('#time'); const word = document.querySelector('#word'); const perWordDuration = 15; const message = "1.60 words would be shown one by one.\r\n2.Each word will appear for only 15 seconds.\r\n3.The candidate has to read the word and write appropriate sentences at the same time.\r\n4.There will be no gap between two simultaneous words.\r\n5.The words can be positive or negative.\r\n6.The duration of WAT is 15 minutes."; alert(message); startTimer(perWordDuration, display);
对应HTML代码
<script src="https://kit.fontawesome.com/bf341fb126.js" crossorigin="anonymous"></script> <!-- Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> <div class="wrapper mt-5"> <header class="text-center pb-4 h1"> Word Association Test </header> <div class="text-center"> <i class="fa fa-clock-o fs-3" aria-hidden="true"></i> </div> <div id="time" class="text-center fs-3 mt-3"></div> <div id="word" class="text-center fs-3 mt-3"></div> </div> <script src="JavaScript/script.js"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
内容的提问来源于stack exchange,提问作者valavbs
相关产品推荐
相关产品推荐

