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

JavaScript array.push添加元素时数组内Date元素被意外修改问题

问题产生原因

这是JavaScript引用类型的典型特性导致的:

  • Date属于引用类型,和数字、字符串这类基础类型不同,变量存储的不是实际的日期值,而是指向内存中Date对象的地址指针。
  • 你的代码里var AD = TodaysDate操作,没有创建新的Date对象,只是把同一个对象的地址赋值给了AD,此时TodaysDate、AD、数组里已经存入的所有date属性,指向的都是内存里同一个Date对象。
  • 调用setDate()方法时,会直接修改这个公共Date对象本身的数值,所有指向它的变量、数组元素读取到的都是修改后的最新值,所以最后所有元素的日期都会变成最后一次修改后的6月13日。
  • 额外说明:直接用console.log()打印引用类型对象时,控制台显示的是你手动展开对象那一刻的值,不是代码执行到打印行的快照,这也是你第一次打印数组就看到日期被改掉的原因。
修复方案

每次需要生成新日期时,基于原日期创建独立的Date副本再操作,不要直接修改复用的同一个Date对象,修复后代码如下:

// globals
var TodaysDate;
var holidays = [];

function ShowHolidays() {
  // 打印时转JSON再解析,拿到当前时刻的数组快照,避免控制台引用延迟显示问题
  console.log(JSON.parse(JSON.stringify(holidays)));
  for (let i = 0; i < holidays.length; i++) {
    console.log("[" + i + "] " + holidays[i].name + " - " + holidays[i].date);
  }
}

function AJSTEST() {
  TodaysDate = new Date();
  // 存入数组时创建Date副本
  holidays.push({ name: "Day1", date: new Date(TodaysDate) });
  ShowHolidays();
  debugger;

  // 基于初始日期创建全新副本再做日期偏移
  var AD = new Date(TodaysDate);
  AD.setDate(AD.getDate() + 2);
  debugger;
  holidays.push({ name: "Day1+2", date: new Date(AD) });
  ShowHolidays();

  // 重新基于初始日期创建副本计算第三个日期,避免修改已有对象
  AD = new Date(TodaysDate);
  AD.setDate(AD.getDate() + 3);
  holidays.push({ name: "Day1+3", date: new Date(AD) });
  ShowHolidays();
  debugger;
}

AJSTEST();

核心修改点:

  • 所有存入数组的Date值,都通过new Date(原日期对象)创建全新的独立实例,保证每个元素的date属性指向互不干扰的Date对象,修改其中一个不会影响其他值
  • 计算偏移日期时,永远基于初始基准日期创建新副本再调用setDate修改,不要直接在已经存入数组的Date对象上调用修改方法
  • 调试打印引用类型时,如果需要保留执行到打印行的即时值,先转成JSON字符串再解析,避免控制台懒加载引用导致的显示误差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:09:34