You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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?


问题分析与解决

核心问题

触发错误的本质原因是循环边界计算错误,伴随潜在的全局变量污染问题:

  1. daysInMonth未正确更新
    切换月份时,daysInMonth变量没有同步更新为当前月份的天数,仍保留了上一个长月份的数值(比如一月的31)。这会导致循环次数变为paddingDays + 31,当i超过paddingDays + 28时,i - paddingDays - 1的索引会超出二月事件数组的长度(索引范围0-27),读取undefined元素触发TypeError。

  2. 全局变量污染
    findMaanedsEvents函数中的循环变量i未用let声明,会成为全局变量。第一次调用后i会残留为requestdata.length,后续调用函数时循环可能直接跳过,导致返回空数组或不完整数组。

  3. 日历容器未清空
    切换月份时如果未清空calendar容器,旧的日期方块会残留,可能导致DOM逻辑混乱,间接影响循环判断。

解决步骤

  1. 强制更新月份天数与前置空白天数
    在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;
    
  2. 修复全局变量问题
    给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;
    }
    
  3. 切换月份时清空日历容器
    在load()函数开头添加清空逻辑:

    function load() {
        // 清空旧日历内容
        calendar.innerHTML = '';
        // 后续的月份计算、事件筛选、填充逻辑...
    }
    

内容的提问来源于stack exchange,提问作者Feltsvinet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 10:50:16