如何为JavaScript对象内深度嵌套的数组节点添加children属性
文件树指定节点追加子节点实现方案
现有数据结构
我当前使用如下树结构表示用户设备上的文件夹内容,结构会随用户机器的实际文件情况动态变化:
var tree = { name: "docs", type: "dir", full: "/home/docs", children: [ { name: "folder2", type: "dir", full: "/home/docs/folder2", children: [ { name: "file2.txt", type: "file", full: "/home/docs/folder2/file2.txt" } ] }, { name: "file1.txt", type: "file", full: "/home/docs/file1.txt" } ] }
结构遵循统一规则:
- 每个节点对应一个文件或目录:
type属性值为"dir"时是目录,值为"file"时是文件 - 目录节点额外包含
children属性,值为该目录下所有子节点组成的数组 - 所有节点都包含
name属性(对应文件夹/文件名),以及全局唯一的full属性(对应该文件/文件夹在用户文件系统中的绝对路径)
已有基础逻辑
目前已编写递归查找算法,可在树结构中查找匹配指定路径的文件夹节点并返回:
function FindChildrenInTree(fullPath, treeObj) { if (treeObj.type != "dir") { return null; } if (treeObj.children == null) { return null } if (treeObj.full == fullPath) { return treeObj; } for (var i = 0; i < treeObj.children.length; i++) { if (treeObj.children[i].full == fullPath) { return treeObj.children[i]; } else { var result = FindChildrenInTree(fullPath, treeObj.children[i]); if (result != null) return result; } } return null; } // 测试调用 console.log(FindChildrenInTree("/home/docs/folder2", tree))
需求说明
现有算法仅能返回匹配到的节点,需要调整逻辑实现直接在原树结构上修改的效果:调用方法时传入3个参数(目标节点的唯一full路径、原tree对象、待添加的children数组),即可为匹配到的目标节点设置指定的children属性,无需返回节点。
实现代码
核心利用JS对象引用传递的特性,递归遍历找到目标节点后直接修改属性即可,修改会自动同步到原树结构:
/** * 为文件树中指定路径的目录节点设置子节点 * @param {string} targetFullPath 目标目录的绝对路径 * @param {object} treeObj 原文件树根节点 * @param {Array} childrenToSet 待设置的子节点数组 * @returns {boolean} 操作是否成功,目标不存在/目标为文件时返回false */ function setNodeChildren(targetFullPath, treeObj, childrenToSet) { // 非目录节点无下级,直接终止 if (treeObj.type !== "dir") return false; // 当前节点命中目标路径 if (treeObj.full === targetFullPath) { treeObj.children = childrenToSet; return true; } // 遍历子节点递归查找 if (Array.isArray(treeObj.children)) { for (const child of treeObj.children) { // 子节点直接命中 if (child.full === targetFullPath) { if (child.type !== "dir") return false; child.children = childrenToSet; return true; } // 递归深入子节点查找,找到即终止遍历 const isFound = setNodeChildren(targetFullPath, child, childrenToSet); if (isFound) return true; } } return false; } // 调用示例 const newChildNodes = [ { name: "file2.txt", type: "file", full: "/home/docs/folder2/file2.txt" }, { name: "newFolder", type: "dir", full: "/home/docs/folder2/newFolder", children: [] } ]; // 给/home/docs/folder2设置新的子节点 setNodeChildren("/home/docs/folder2", tree, newChildNodes);
补充说明
- 如果需要在原有子节点基础上追加而非覆盖,将赋值逻辑替换为数组合并即可:
// 追加而非覆盖的写法 treeObj.children = Array.isArray(treeObj.children) ? [...treeObj.children, ...childrenToSet] : childrenToSet; - 方法返回布尔值可用于后续逻辑判断,比如路径不存在、路径对应文件而非目录的异常场景处理。
内容的提问来源于stack exchange,提问作者Aditya Mishra
相关产品推荐
相关产品推荐

