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
相关产品推荐
相关产品推荐

