JS遍历对象映射到目标结构时如何避免覆盖原有值?
表单重复区块数据转换值覆盖修复方案
问题根因
出现值覆盖的核心原因是JavaScript对象引用复用:
- 循环处理
_copy_0、_copy_1这类重复地址字段时,没有为每个地址条目创建独立的新对象,而是反复修改同一个提前声明的模板对象,最终推入数组的所有条目都指向同一个内存地址,循环结束后所有条目都会显示最后一次赋值的结果。 - 之前尝试的「推入数组前先传对象」方案未生效,本质也是没有创建新对象/做对象拷贝,推入数组的仍然是同一个对象的引用。
修复实现代码
不需要提前声明可复用的地址模板对象,直接按字段命名规则分组,每识别到一个新的地址条目索引就初始化全新的空对象,从根源避免引用污染:
function transformFormData(formData) { const addressMap = {}; // 正则匹配表单字段规则:主地址无后缀,重复地址带_copy_x后缀 const fieldRegex = /^question_1([1-5])_(address|city|state|zip|country)(?:_copy_(\d+))?$/; Object.entries(formData).forEach(([key, value]) => { const match = key.match(fieldRegex); if (!match) return; // 提取字段名、条目索引:主地址索引为0,copy_0对应索引1,copy_1对应索引2,依次顺延 const [, , fieldName, copyIndex] = match; const entryIndex = copyIndex === undefined ? 0 : Number(copyIndex) + 1; // 核心逻辑:当前索引不存在对应条目时,才创建全新空对象,彻底避免引用复用 if (!addressMap[entryIndex]) { addressMap[entryIndex] = {}; } addressMap[entryIndex][fieldName] = value; }); // 按索引正序排序后转为数组输出 return Object.keys(addressMap) .sort((a, b) => Number(a) - Number(b)) .map(index => addressMap[index]); } // 测试用例 const data = { question_11_address: "124 Aspen Rd", question_12_city: "South Orange", question_13_state: "NJ", question_14_zip: "07052", question_15_country: "USA", question_11_address_copy_0: "123 Main St", question_12_city_copy_0: "Jersey City", question_13_state_copy_0: "NJ", question_14_zip_copy_0: "07302", question_15_country_copy_0: "USA", question_11_address_copy_1: "110 Marrin St", question_12_city_copy_1: "Hoboken", question_13_state_copy_1: "NJ", question_14_zip_copy_1: "07302", question_15_country_copy_1: "USA", }; const finalAddresses = transformFormData(data);
运行后输出的结构完全符合预期,不会再出现值覆盖问题。
避坑要点
- 禁止在循环外部声明通用模板对象(比如
const tempAddr = {}),在循环内修改属性后直接push到数组,这种写法必然触发引用覆盖 - 如果一定要使用模板对象,每次push前必须做浅拷贝生成新对象:
addressList.push({...tempAddr}) - 多ID、多联系人等其他重复表单区块的转换逻辑完全通用,只需修改正则匹配的字段规则即可适配。
内容的提问来源于stack exchange,提问作者London804
相关产品推荐
相关产品推荐

