使用Array.forEach()设置不同日期却全部填充为最后一个日期的问题
哈哈,这个坑我踩过好多次!核心问题大概率是你在循环里不小心复用了同一个对象引用,而非每次都创建全新的对象——虽然你贴的代码里写了{ date: new Date(el), ... },但我猜你省略的...部分可能引用了一个循环外部定义的对象,或者你把对象的创建逻辑放到了循环外面,导致每次push的都是同一个对象的引用,最后数组里所有元素都会指向最后一次修改的那个对象。
先拆解下你的代码:你定义了局部变量let arr: any[] = [],但forEach里却用this.arr.push——如果this.arr是类的实例属性,和局部的arr不是同一个东西,这会导致局部数组根本没被用到,但这不是日期全部变成最后一个的主因,更常见的问题是对象引用复用。
错误示例(你可能的真实代码)
如果你的代码实际是这样的,就会出现所有日期都变成最后一个的情况:
let dates: string[] = ['2018-01-22', '2018-01-28', '2018-01-30', '2018-02-11']; let arr: any[] = []; // 错误:把对象放在循环外,所有push的都是同一个引用 let tempObj = { otherProp: '默认值' }; dates.forEach(el => { tempObj.date = new Date(el); arr.push(tempObj); });
这里的tempObj是同一个对象,每次循环只是修改它的date属性,然后把同一个引用推入数组。数组里的所有元素其实都指向这一个对象,所以最后所有元素的date都会变成最后一次循环的2018-02-11。
正确写法
解决的关键是每次循环都创建全新的对象实例,确保每个推入数组的对象都是独立的:
let dates: string[] = ['2018-01-22', '2018-01-28', '2018-01-30', '2018-02-11']; let arr: any[] = []; dates.forEach(el => { // 每次循环都生成新对象,所有属性都是独立的 arr.push({ date: new Date(el), // 这里放你的其他属性,比如动态值或固定值都可以 otherProp: '独立属性值' }); });
如果你的...部分需要复用一些基础属性,也要确保是每次创建新的对象(比如用对象展开语法创建副本):
// 基础属性模板 const baseObj = { type: 'event', status: 'pending' }; dates.forEach(el => { // 用展开语法创建baseObj的副本,再添加date属性 arr.push({ ...baseObj, date: new Date(el) }); });
这样每次push的都是新对象,每个对象的date都是独立的Date实例,不会出现覆盖的情况。
另外,还要注意你代码里的this.arr和局部arr的混淆问题——如果你的意图是使用局部数组,就把this.arr.push改成arr.push;如果是要用类的实例属性,就删掉局部的let arr: any[] = [],避免变量冲突。
内容的提问来源于stack exchange,提问作者Waleed93

