JavaScript中如何跳过嵌套对象未知键层级完成数据结构转换?
核心结论
- 完全可以跳过未知数字ID的冗余层级,且跳过逻辑不需要依赖children属性是否存在:所有随机数字ID作为键的层级,本质是
{ [随机ID]: 实际节点 }的索引结构,不需要提前获取ID值,直接通过Object.values()取对象所有属性值即可拿到真实节点,完全不需要关心外层键名是什么,和节点内部有没有children没有关系。 - 两种转换模式都支持:既可以生成不改动原对象的全新标准化数组,也可以原地修改原对象完成结构转换。
结构对照
以下为原始输入结构和目标输出结构的示例:
// 原始输入:数字ID为冗余外层键 const rawData = { "12345": { name: "张三", age: 40, children: { "67890": { name: "张小明", age: 12, children: { "13579": { name: "张小豆", age: 3, children: {} } } }, "24680": { name: "张小红", age: 10, children: {} } } } } // 目标输出:无ID冗余层,children为数组类型 const target = [ { name: "张三", age: 40, children: [ { name: "张小明", age: 12, children: [ { name: "张小豆", age: 3, children: [] } ] }, { name: "张小红", age: 10, children: [] } ] } ]
方案1:生成全新标准化数组(不修改原对象)
递归遍历每一层ID包裹对象,拷贝节点基础属性生成新节点,递归处理children生成标准数组,全程不改动原始输入的内容:
/** * 转换ID包裹结构为标准children数组,不修改原对象 * @param {Object} idWrappedObj 数字ID包裹的层级对象 * @returns {Array} 标准化节点数组 */ function convertToNewArray(idWrappedObj) { const result = [] // 直接遍历所有值取真实节点,完全忽略ID键名 for (const node of Object.values(idWrappedObj)) { const newNode = { name: node.name, age: node.age, children: node.children ? convertToNewArray(node.children) : [] } result.push(newNode) } return result } // 调用示例 const standardData = convertToNewArray(rawData)
方案2:原地修改原对象
直接改动原始输入的对象引用,内存占用更低,递归过程中直接将节点的children属性从ID索引对象替换为标准数组,无children的节点统一赋值为空数组:
/** * 原地修改原对象结构,移除ID冗余层 * @param {Object} idWrappedObj 数字ID包裹的层级对象 * @returns {Array} 标准化节点数组(原对象引用已被修改) */ function convertInPlace(idWrappedObj) { const nodeList = [] for (const node of Object.values(idWrappedObj)) { node.children = node.children ? convertInPlace(node.children) : [] nodeList.push(node) } return nodeList } // 调用示例:原始rawData内部结构会被直接修改 const modifiedData = convertInPlace(rawData)
扩展说明
- 如果需要保留原始数字ID,只需要遍历的时候同时取键和值即可,将
for (const node of Object.values(idWrappedObj))替换为for (const [id, node] of Object.entries(idWrappedObj)),再给节点添加id属性即可。 - 该逻辑自动适配同级多节点的场景,同一ID层下的多个节点会按遍历顺序存入数组,不会丢失数据。
内容的提问来源于stack exchange,提问作者kt74ys
相关产品推荐
相关产品推荐

