
本文介绍一种高效、可读性强的方法,将包含 `items` 数组(每个 item 是形如 `{ [keyprop]: name, quantity: value }` 的对象)的源数组,转换为每个顶层对象直接携带动态属性(如 `crust: 2.2`, `dust: 34`)的新数组。
在实际开发中,我们常遇到类似场景:原始数据结构为“订单+明细项”嵌套形式,但前端渲染或后续处理更倾向扁平化的字段映射(例如将商品名作为属性键、数量作为值)。针对该需求,最清晰且性能可控的方案是使用 Array.prototype.map() 配合对象解构与动态赋值。
以下是一个健壮、生产就绪的实现:
function flattenItems(arr) {
return arr.map(obj => {
// 浅拷贝原对象,避免污染输入数据
const result = { ...obj };
// 移除 items 字段(后续将明细展开为顶层属性)
delete result.items;
// 遍历每个明细项,提取 productX 属性值作为新键,quantity 作为值
obj.items?.forEach(item => {
// 找出非 'quantity' 的属性名(即 productOne/productTwo/productThree 等)
const keyField = Object.keys(item).find(key => key !== 'quantity');
if (keyField && typeof item[keyField] === 'string' && 'quantity' in item) {
const propName = item[keyField]; // 如 "crust", "dust"
const propValue = item.quantity; // 如 2.2, 34
result[propName] = propValue;
}
});
return result;
});
}✅ 使用示例:
const firstArray = [
{
amount: 343,
code: "RCU8YI0NKS",
items: [
{ productOne: "crust", quantity: 2.2 },
{ productTwo: "dust", quantity: 34 }
],
user_id: "wewewefwOHG22323kj"
},
{
amount: 343,
code: "RCU8YI0NKS",
items: [
{ productTwo: "dust", quantity: 32 },
{ productThree: "must", quantity: 34 }
],
user_id: "m2LgLRD9MEVNAX56JTpRYDkOOjd2"
}
];
console.log(flattenItems(firstArray));
// 输出即为目标格式 secondArray⚠️ 注意事项:
- 该方法假设每个 item 中有且仅有一个非 quantity 的字符串键(如 productOne),其值即为要注入的属性名;若存在多个非 quantity 字段,请根据业务逻辑明确提取规则(例如优先取 productOne,或合并所有 product* 值)。
- 使用可选链 obj.items?.forEach(...) 提升容错性,避免 items 缺失时抛错。
- 若需深度克隆(而非浅拷贝),可引入 structuredClone()(现代环境)或 Lodash 的 cloneDeep()。
- 时间复杂度为 O(n × m),其中 n 是外层数组长度,m 是平均 items 长度——这是该问题的理论最优解,无可避免的遍历开销。
总结:无需依赖外部库,仅用原生 JavaScript 即可安全、高效完成嵌套到扁平的结构转换;关键在于精准识别动态键名,并通过对象扩展语法完成属性注入。










