JavaScript切换短天数月份时出现Uncaught TypeError问题求助
本人是JavaScript新手,有Arduino和Python编程经验,正跟随教程开发按月展示事件的消防部门排班日历。不填充事件时程序正常;填充事件后,当切换到天数少于上一个月的月份(如二月28天,此前为一月31天),会触发Uncaught TypeError:前28次数组读取正常,之后报错,但控制台显示对应月份事件数组的长度与当月天数匹配。
页面加载时通过jQuery从远程数据库获取全年数据存入requestdata数组;切换月份时调用load()函数更新视图,自定义findMaanedsEvents(maaned)函数筛选对应月份事件,返回的数组数据及长度均正确。
事件筛选代码
function findMaanedsEvents(maaned) { let maanedens_events = []; let eventtaeller = 0; for (i = 0; i < requestdata.length; i++) { let reqm = requestdata[i]['dato'].split('-'); if (reqm[1] == maaned) { maanedens_events[eventtaeller] = requestdata[i]; eventtaeller ++; } } return maanedens_events; }
日历事件填充代码
for(let i = 1; i <= paddingDays + daysInMonth; i++) { const daySquare = document.createElement('div'); daySquare.classList.add('day'); if (i > paddingDays) { daySquare.innerText = i - paddingDays; dagens_events = dagsevents[i - paddingDays - 1]['bm1'] + "\n" + dagsevents[i - paddingDays - 1]['bm2'] + "\n" + dagsevents[i - paddingDays - 1]['bm3'] + "\n" + dagsevents[i - paddingDays - 1]['bm4'] + "\n" + dagsevents[i - paddingDays - 1]['bm5']; const eventDiv = document.createElement('div'); if (dagsevents[i - paddingDays - 1]['helligdag'] == 1) { eventDiv.classList.add('helligdag_event'); } else { eventDiv.classList.add('event'); } eventDiv.innerText = dagens_events; daySquare.appendChild(eventDiv); console.log(dagsevents[i - paddingDays - 1]['bm1']); } else { daySquare.classList.add('padding'); } calendar.appendChild(daySquare); }
求助:为何数组长度正确的情况下,切换短天数月份仍会触发TypeError?
核心问题
触发错误的本质原因是循环边界计算错误,伴随潜在的全局变量污染问题:
daysInMonth未正确更新
切换月份时,daysInMonth变量没有同步更新为当前月份的天数,仍保留了上一个长月份的数值(比如一月的31)。这会导致循环次数变为paddingDays + 31,当i超过paddingDays + 28时,i - paddingDays - 1的索引会超出二月事件数组的长度(索引范围0-27),读取undefined元素触发TypeError。全局变量污染
findMaanedsEvents函数中的循环变量i未用let声明,会成为全局变量。第一次调用后i会残留为requestdata.length,后续调用函数时循环可能直接跳过,导致返回空数组或不完整数组。日历容器未清空
切换月份时如果未清空calendar容器,旧的日期方块会残留,可能导致DOM逻辑混乱,间接影响循环判断。
解决步骤
强制更新月份天数与前置空白天数
在load()函数开头,重新计算当前月份的daysInMonth和paddingDays,确保数值准确:// 示例:获取当前月份天数(注意JavaScript月份是0-based,比如二月对应1) const currentDate = new Date(year, currentMonth, 0); const daysInMonth = currentDate.getDate(); // 计算前置空白天数 const firstDayOfMonth = new Date(year, currentMonth, 1).getDay(); const paddingDays = firstDayOfMonth === 0 ? 6 : firstDayOfMonth - 1;修复全局变量问题
给findMaanedsEvents中的循环变量i添加let声明,避免全局污染:function findMaanedsEvents(maaned) { let maanedens_events = []; let eventtaeller = 0; // 添加let声明i for (let i = 0; i < requestdata.length; i++) { let reqm = requestdata[i]['dato'].split('-'); if (reqm[1] == maaned) { maanedens_events[eventtaeller] = requestdata[i]; eventtaeller ++; } } return maanedens_events; }更简洁的写法可以用
push替代手动维护索引:function findMaanedsEvents(maaned) { let maanedens_events = []; for (let i = 0; i < requestdata.length; i++) { let reqm = requestdata[i]['dato'].split('-'); if (reqm[1] == maaned) { maanedens_events.push(requestdata[i]); } } // 按日期排序,确保数组索引与日期对应 maanedens_events.sort((a, b) => new Date(a.dato) - new Date(b.dato)); return maanedens_events; }切换月份时清空日历容器
在load()函数开头添加清空逻辑:function load() { // 清空旧日历内容 calendar.innerHTML = ''; // 后续的月份计算、事件筛选、填充逻辑... }
内容的提问来源于stack exchange,提问作者Feltsvinet

