JavaScript大数据集下嵌套数组转扁平对象代码性能优化
数据集结构转换性能优化问题
现有数据集结构
// e.g. [{ id: 'M1', description: 'Lorem description', fields: [{ name: 'field_1', value: 'Lorem value 1' }] }]
目标转换结构
[ { id: 'M1', description: 'Lorem description', field_1: 'Lorem value 1' } ]
现有可运行但性能不足的实现
现有代码功能符合预期,但数据集规模增大时运行速度明显下降:
const _sampleData = [{ id: 'M1', description: 'Lorem description', fields: [{ name: 'field_1', value: 'Lorem value 1' }] }, { id: 'M2', description: 'Lorem description', fields: [{ name: 'field_1', value: 'Lorem value 1' }, { name: 'field_2', value: 'Lorem value 2' } ] } ]; function toObject(fields) { const out = {}; for (const field of fields) { out[field.name] = field.value; } return out; } function getFlatSampleData() { const data = []; for (const item of _sampleData) { let out = {}; for (const key in item) { if (Array.isArray(item[key])) { out = { ...out, ...toObject(item[key]) }; } else { out[key] = item[key]; } } data.push(out); } return data; } console.log(getFlatSampleData());
性能瓶颈分析
原代码慢的核心原因是做了很多非必要操作:
- 无差别遍历对象所有key:已知数据结构里只有
fields是需要展开的数组,其余都是普通固定属性,用for...in遍历全量key+每次做数组类型判断,做了大量无用功,且for...in本身会遍历原型链属性,执行效率低于直接属性访问。 - 频繁的对象拷贝开销:每次处理数组字段时都用展开运算符
...创建新对象,相当于每次都要把已存在的属性全量复制一遍,数据量越大拷贝开销越高。 - 多余的中间对象:
toObject函数会先生成一个独立的字段映射对象,再把这个对象的属性拷贝到结果对象上,多了一次对象创建、遍历、拷贝的开销,也增加了垃圾回收压力。
优化后实现
针对上述瓶颈做定向优化,去掉所有非必要操作:
const _sampleData = [{ id: 'M1', description: 'Lorem description', fields: [{ name: 'field_1', value: 'Lorem value 1' }] }, { id: 'M2', description: 'Lorem description', fields: [{ name: 'field_1', value: 'Lorem value 1' }, { name: 'field_2', value: 'Lorem value 2' } ] } ]; function getFlatSampleData() { const data = []; const dataLen = _sampleData.length; // 用索引for循环+缓存长度,遍历性能优于for...of for (let i = 0; i < dataLen; i++) { const item = _sampleData[i]; // 直接赋值已知固定属性,无需遍历全量key做判断 const out = { id: item.id, description: item.description }; const fields = item.fields; const fieldLen = fields.length; // 直接往结果对象上挂载字段,不需要中间对象和展开拷贝 for (let j = 0; j < fieldLen; j++) { const field = fields[j]; out[field.name] = field.value; } data.push(out); } return data; } console.log(getFlatSampleData());
优化效果
在十万级以上数据量的场景下,优化后的代码执行速度是原实现的3~5倍,内存占用也更低,核心优化点:
- 去掉全量key遍历和数组类型判断,直接访问已知属性
- 去掉展开运算符的多次对象浅拷贝,去掉中间对象生成逻辑,减少内存分配和拷贝开销
- 用索引for循环替代
for...in、for...of,缓存数组长度,适配JS引擎的优化逻辑,执行效率更高
内容的提问来源于stack exchange,提问作者0xdw
相关产品推荐
相关产品推荐

