JavaScript/TypeScript中forEach嵌套map数据覆盖问题及ES6简化实现
问题解答
1. 第一次迭代数据被覆盖的原因
JavaScript里的对象属于引用类型,你代码里的数组b存储的是两个对象的引用。循环过程中:
- 第一次遍历
a的NameOne元素时,修改了b里两个对象的data属性,随后把这两个对象的引用push到c中; - 第二次遍历
a的NameTwo元素时,依旧直接修改b里那两个原对象的data属性,而c里之前存入的元素和b里的对象是同一个引用,因此之前的NameOne和WeekOne会被新值覆盖。
最终c里的四个元素其实重复指向b里的两个对象,所以所有data都显示第二次迭代的结果。
2. ES6简便实现方法
核心是每次迭代时创建新对象,避免修改原对象的引用。可以用flatMap结合对象扩展运算符...实现,代码更简洁:
const a = [ { name: 'NameOne', weekName: 'WeekOne' }, { name: 'NameTwo', weekName: 'WeekTwo' }, ]; const bTemplate = [ { id: 'Name', type: 'text', data: '' }, { id: 'Week', type: 'text', data: '' }, ]; // 生成期望的c数组 const c = a.flatMap(element => { return bTemplate.map(template => { // 复制模板对象,根据id赋值对应data return { ...template, data: template.id === 'Name' ? element.name : element.weekName }; }); }); console.log(c);
代码说明:
flatMap:遍历a的每个元素,返回的数组会自动展开,避免出现嵌套数组;- 扩展运算符
...template:复制模板对象的所有属性,创建新对象,不会修改原bTemplate的内容; - 三元运算符替代多分支if,简化逻辑。
运行后会得到期望输出:
[ { id: 'Name', type: 'text', data: 'NameOne' }, { id: 'Week', type: 'text', data: 'WeekOne' }, { id: 'Name', type: 'text', data: 'NameTwo' }, { id: 'Week', type: 'text', data: 'WeekTwo' } ]
内容的提问来源于stack exchange,提问作者R.H
相关产品推荐
相关产品推荐

