循环向数组添加对象时为何所有元素均为同一对象?
问题分析与修复
核心问题:Date对象的引用特性
你遇到的问题根源在于Date是引用类型——循环中你反复修改同一个beginning对象,而数组里所有事件的beginning字段都指向这个对象。每次调用setDate/setMonth等方法时,这个对象的实际值被修改,导致数组中所有已添加事件的beginning同步变化,最终所有元素都指向最后一次修改后的日期。
次要问题:数组concat的错误用法
response.concat(periodicalEventsArr)不会修改原response数组,因为concat方法返回新数组,原数组保持不变。需要改用push结合展开运算符来合并数组。
修复后的代码
let response: TEventResponse[] = []; for (let i = 0; i < events.length; i++) { let e = events[i]; if (!e.isPeriodical) { const event: TEventResponse = { beginning: e.beginTime, ending: e.endTime, title: e.title, description: e.description, place: e.place, }; response.push(event); } else { let beginning = new Date(e.beginTime); const upperDate = new Date(); upperDate.setFullYear(year); upperDate.setMonth(month + 1); upperDate.setDate(1); const lowerDate = new Date(); lowerDate.setFullYear(year); lowerDate.setMonth(month); lowerDate.setDate(1); let dateBoundary = e.dateBoundary || upperDate; if (dateBoundary >= upperDate) { const periodicalEventsArr: TEventResponse[] = []; while (beginning <= dateBoundary && beginning < upperDate) { if (beginning >= lowerDate) { // 关键修复:创建新的Date对象,避免复用同一引用 const event: TEventResponse = { beginning: new Date(beginning), ending: e.endTime, title: e.title, description: e.description, place: e.place, }; periodicalEventsArr.push(event); } const n = e.repeatPeriod!; switch (e.repeatPeriodUnit) { case "DAY": beginning.setDate(beginning.getDate() + n); break; case "WEEK": beginning.setDate(beginning.getDate() + n * 7); break; case "MONTH": beginning.setMonth(beginning.getMonth() + n); break; case "YEAR": beginning.setFullYear(beginning.getFullYear() + n); break; } } // 修复数组合并:将周期事件真正添加到response中 response.push(...periodicalEventsArr); } } } return response;
关键修改点说明
- 独立Date对象:生成每个周期事件时,用
new Date(beginning)复制当前日期值,让每个事件的beginning都是独立对象,后续修改原beginning不会影响已添加的事件。 - 修正数组合并:用
response.push(...periodicalEventsArr)替代concat,确保周期事件被真正添加到结果数组。 - 简化边界赋值:用
e.dateBoundary || upperDate替代冗余的if-else判断,精简代码。
内容的提问来源于stack exchange,提问作者argom01
相关产品推荐
相关产品推荐

