如何在JavaScript中重构含嵌套对象的对象数组?
问题:展开嵌套对象属性为平级键值对
我有一个JavaScript对象数组,部分元素包含ZAP_DP、ZAP_EL等嵌套对象,需要将这些嵌套对象的属性展开为平级键值对(比如把ZAP_DP的acttyp改为ZAP_DP_acttyp),但尝试的代码无法得到预期结果,请求排查错误并实现需求。
原始数组结构
const data= [ { id: '6397f6f46b18bc89cb37053c', cost_center: null, plant: null, material: null }, { id: '6397f7166b18bc89cb372ff7', cost_center: 'C118as0008', short_description: 'LINE PasdNG ALL', plant: 'K1as8', material: '300006', material_name: 'DRILLO PBJ 22g MT (12 pcs x 8 ib)', base_quantity: 218.995, ZAP_DP: { acttyp: 'ZAP_DP', stdval: 0.224, unit: 'HR' }, ZAP_EL: { acttyp: 'ZAP_EL', stdval: 0.224, unit: 'HR' }, ZAP_LH: { acttyp: 'ZAP_LH', stdval: 0.224, unit: 'HR' }, ZAP_OT: { acttyp: 'ZAP_OT', stdval: 0.224, unit: 'HR' }, kwh: 35.46, no_mc_mmbtu: 5, noempl: 50 }, { id: '6397f7166b18bc89cb373003', cost_center: 'C11asd9', short_description: 'LINE WAasdAT FOX', plant: 'K1aas8', material: '300007', material_name: 'asBAasd0g GT (60 pcs)', base_quantity: 28.816, ZAP_DP: { acttyp: 'ZAP_DP', stdval: 0.33, unit: 'HR' }, ZAP_EL: { acttyp: 'ZAP_EL', stdval: 0.33, unit: 'HR' }, ZAP_GS: { acttyp: 'ZAP_GS', stdval: 0.33, unit: 'HR' }, ZAP_LH: { acttyp: 'ZAP_LH', stdval: 0.33, unit: 'HR' }, ZAP_OT: { acttyp: 'ZAP_OT', stdval: 0.33, unit: 'HR' }, kwh: 72.67, no_mc_mmbtu: 1.85, noempl: 14.5 }, ]
期望重构后的结构
[ { id: '6397f6f46b18bc89cb37053c', cost_center: null, plant: null, material: null }, { id: '6397f7166b18bc89cb372ff7', cost_center: 'C118as0008', short_description: 'LINE PasdNG ALL', plant: 'K1as8', material: '300006', material_name: 'DRILLO PBJ 22g MT (12 pcs x 8 ib)', base_quantity: 218.995, ZAP_DP_acttyp: 'ZAP_DP', ZAP_DP_stdval: 0.33, ZAP_DP_unit: 'HR' , ZAP_EL_acttyp: 'ZAP_EL', ZAP_EL_stdval: 0.33, ZAP_EL_unit: 'HR' , ZAP_LH_acttyp: 'ZAP_LH', ZAP_LH_stdval: 0.33, ZAP_LH_unit: 'HR' , ZAP_OT_acttyp: 'ZAP_OT', ZAP_OT_stdval: 0.33, ZAP_OT_unit: 'HR' , kwh: 35.46, no_mc_mmbtu: 5, noempl: 50 }, { id: '6397f7166b18bc89cb373003', cost_center: 'C11asd9', short_description: 'LINE WAasdAT FOX', plant: 'K1aas8', material: '300007', material_name: 'asBAasd0g GT (60 pcs)', base_quantity: 28.816, ZAP_DP_acttyp: 'ZAP_DP', ZAP_DP_stdval: 0.33, ZAP_DP_unit: 'HR' , ZAP_EL_acttyp: 'ZAP_EL', ZAP_EL_stdval: 0.33, ZAP_EL_unit: 'HR' , ZAP_GS_acttyp: 'ZAP_GS', ZAP_GS_stdval: 0.33, ZAP_GS_unit: 'HR' , ZAP_LH_acttyp: 'ZAP_LH', ZAP_LH_stdval: 0.33, ZAP_LH_unit: 'HR' , ZAP_OT_acttyp: 'ZAP_OT', ZAP_OT_stdval: 0.33, ZAP_OT_unit: 'HR' , kwh: 72.67, no_mc_mmbtu: 1.85, noempl: 14.5 }, ]
尝试的错误代码
const transformed = data.map((el)=>{ for (const property in el) { for (const prop in property){ } console.log(`${property}:${el[property]}`); } })
代码错误分析
- 内层循环逻辑错误:
property是对象的键名(字符串类型),不是嵌套对象,所以for (const prop in property)遍历的是字符串的内置属性,完全达不到遍历嵌套对象属性的目的。 - 未构建返回值:
map函数需要返回处理后的新对象,但你的代码仅做了console.log,最终transformed数组会全是undefined。 - 未区分普通属性与嵌套对象:没有判断当前属性值是否是需要展开的嵌套对象,直接遍历所有属性却未做对应处理。
正确实现方法
const transformed = data.map(item => { const newItem = {}; // 遍历当前对象的所有键 for (const key in item) { const value = item[key]; // 判断是否是需要展开的嵌套对象(排除null,因为typeof null === 'object') if (typeof value === 'object' && value !== null) { // 遍历嵌套对象的属性,拼接新键名 for (const nestedKey in value) { newItem[`${key}_${nestedKey}`] = value[nestedKey]; } } else { // 普通属性直接复制 newItem[key] = value; } } return newItem; }); console.log(transformed);
实现说明
- 用
map遍历原数组的每个元素,为每个元素创建一个空的新对象newItem。 - 遍历当前元素的所有键,判断值是否为非null的对象:
- 如果是嵌套对象,遍历其属性,将原键名+下划线+嵌套键名作为新键,对应值添加到
newItem。 - 如果是普通属性,直接将键值对复制到
newItem。
- 如果是嵌套对象,遍历其属性,将原键名+下划线+嵌套键名作为新键,对应值添加到
- 返回处理后的
newItem,最终得到符合要求的数组。
内容的提问来源于stack exchange,提问作者JS24
相关产品推荐
相关产品推荐

