JavaScript提取嵌套对象最底层属性实现扁平化的最佳实践
嵌套对象提取叶子属性的最佳实践
需求场景
需要将多层嵌套的对象处理为单层平面对象,仅保留最底层的基础类型属性,丢弃所有中间嵌套层级,示例如下:
初始对象
const start = { a: 1, b: { c: 2, d: 3 }, e: 4, f:{ g: 5 } }
目标输出
const wanted = { a: 1, c: 2, d: 3, e: 4, g: 5 }
要求避免逐属性手动赋值、避免在对象构建语句外生成冗余中间变量。
推荐实现:可复用递归扁平化函数
一次编写即可适配任意深度、任意属性数量的嵌套对象,无冗余变量,维护成本极低:
/** * 递归提取嵌套对象所有叶子属性,生成单层平面对象 * @param {Object} obj 待处理的嵌套对象 * @returns {Object} 扁平化后的结果 */ function flattenLeafProps(obj) { const result = {} for (const [key, value] of Object.entries(obj)) { // 判定为普通对象则递归深入遍历,可根据业务需求调整判定规则 const isPlainObject = value !== null && typeof value === 'object' && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype if (isPlainObject) { // 递归结果合并到最终返回值 Object.assign(result, flattenLeafProps(value)) } else { // 非普通对象判定为叶子属性,直接挂载 result[key] = value } } return result } // 一行调用即可得到目标结果 const simplified = flattenLeafProps(start)
上述代码处理示例输入时,输出和预期目标完全一致。
场景适配调整
你可以根据自己的业务数据结构调整判定规则,适配不同场景:
- 如果需要将数组作为叶子属性整体保留,现有逻辑已经支持,不会展开数组内容
- 如果需要展开数组内嵌套的对象,可以新增数组类型判断分支,遍历数组元素递归处理
- 如果存在不同层级同名属性的情况,可以给递归函数增加路径前缀参数,生成类似
b.c、f.g格式的唯一key,避免后遍历的属性值覆盖之前的属性 - 如果项目已经引入Lodash这类通用工具库,可以直接使用内置的
_.flattenObject方法,根据需求配置展开规则即可,无需自行实现递归逻辑
不推荐方案的问题
- 手动逐属性映射:属性数量多、嵌套层级深时代码量极大,后续属性增删改需要同步修改映射关系,维护成本极高
- 作用域外解构生成临时变量:会污染当前作用域,属性较多时会产生大量无用临时变量,代码冗余度高
- 对象字面量内直接展开嵌套层:比如
{ a: start.a, ...start.b, e: start.e }这类写法仅适用于固定2层嵌套的场景,层级更深时仍需手动写每一层展开,无通用性,且中间层为undefined时会直接抛出错误,容错性差
内容的提问来源于stack exchange,提问作者philale
相关产品推荐
相关产品推荐

