对象数组遍历修改

yan_wu110
  • 3
新手上路,请多包涵
let dataObj = new Array(7).fill({'week': "",'list':[]})
let convertDataobj = dataObj.map((currentValue,index)=>{
    currentValue.week = index
    return currentValue
 })

想让week 递增,
但是这样返回week值均为6image.png

回复
阅读 212
3 个回答
✓ 已被采纳

试试这段代码:

let dataObj = new Array(7).fill({ "week": "", "list": [] });

for (let i = 1; i < dataObj.length; i++) {
    console.log(`[${i}]: ${dataObj[i] === dataObj[0]}`);
}

可以看到连续打印出来 6 个 true,这是因为 fill(obj) 会直接拿一个对象填充整个数组,数组的每个元素都是同一个对象的引用 —— 这就是代码不符合预期的根本原因。

既然知道原因,要解决就容易了,只需要让 fill 填充的每个元素都是新的对象。那么很遗憾,不能直接从 fill 想办法解决,因为要给 fill 的参数就是对象本身,fill 不会去 copy,也不能进行其他处理。

那么这里只以先产生数组,再进行一次 map 操作。但是直接这样 map 是不行的!!!

let dataObj = new Array(7).map(() => ({ "week": "", "list": [] }));
console.log(dataObj[0]);

可以看到 dataObj[0]undefined,如果直接打印 dataObj 可以看到

[ <7 empty items> ]

好吧,这是因为 JavaScript Array 构造函数的奇特之处,如果 Array 是使用一长度来构造,它会产生一个 length 是指定长度,但没有实际元素(连 undefinded 都不是,是真的「没有」);所以既然连元素都没有,从一个个元素进行的 map 操作实际就没进行。

所以 ,改进方法是,先填充任意值(比如 undefined 或者 0),再来 map

let dataObj = new Array(7)
    .fill(0)
    .map(() => ({ "week": "", "list": [] }));

还有另外一个办法,使用 Array.from,它会把一个 Array Like 对象变成真正的数组(这个 Array Like 对象基本上只要有 length 就行)。Array.from 的第 2 个参数可以是一个 map 函数,所以它会在转换数据的时候一次性映射过去,

let dataObj = Array.from(
    new Array(7),    // 第 1 个参数是 Array Like 对象,这里给 { length: 7 } 是一样的效果
    () => ({ "week": "", "list": [] })
);

除了用 map 之外,也可以直接给对象每个元素赋值,但是注意前面提到的“empty items”问题,只能用 for 循环,不能用 forEach 方法

let dataObj = new Array(7);
for (let i = 0; i < dataObj.length; i++) {
    dataObj[i] = { "week": "", "list": [] };
}

最后说明一下,同样是 { "week": "", "list": [] },为什么放在 fill() 里就是同一个对象,但在 map 的时候会是不同的对象……

因为 map 的参数是一个函数,每次映射时都会调用一次,每次调用都会在函数内部(局部)产生一个新的对象。

that's all.

这样赋值currentValue.week = index,循环结束week取得是index最后的值,修改如下

let convertDataobj = dataObj.map((currentValue,index)=>{
    return {
        week: index,
        list: []
    }
}
)
三十六路云雨落
  • 2
新手上路,请多包涵

主要原因是fill后面的参数是一个对象,导致所有数组里面数据都引用了该对象。而map函数中却只是修改对象,并未生成新对象
一种思路是不修改map情况下,保证dataObj中数据不共用一个对象
还有一种思路是map后面函数返回一个新对象

new Array(7).fill().map((val, i) => ({ week: i, list: []}))
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏