You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Lodash的cloneDeepWith更新嵌套对象的指定path值?

问题描述

我有如下嵌套对象:

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["XXX"],
  type: "row"
};

需要遍历所有含id的节点,将数组const newPath = ["A", "B", "C"];追加到每个节点的path属性前,最终目标对象如下:

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["A", "B", "C", "XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["A", "B", "C", "XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["A", "B", "C", "XXX"],
  type: "row"
};

我尝试使用Lodash的cloneDeepWith函数实现:

let updatedObj = cloneDeepWith(obj, (node) => {
  if (node.id) {
    node = { ...node, path: [...newPath, ...node.path] };
    console.log("updated : ", node)
  }
});

控制台能打印出正确更新后的节点,但updatedObj未正确返回更新后的对象,请问该如何解决?


解决方法

问题根源

cloneDeepWith的自定义迭代函数必须返回修改后的节点,否则Lodash会沿用默认的克隆结果。你当前代码只是修改了局部变量node,但没有将其返回,所以最终的克隆对象并未应用修改。

修正后的cloneDeepWith代码

只需在修改节点后将其返回即可:

const newPath = ["A", "B", "C"];
const updatedObj = cloneDeepWith(obj, (node) => {
  if (node.id) {
    // 返回修改后的节点,替换默认克隆结果
    return { ...node, path: [...newPath, ...node.path] };
  }
  // 无id的节点返回undefined,让Lodash按默认逻辑处理
});

无依赖替代方案:手动递归遍历

如果不想使用Lodash,也可以自己实现递归遍历修改:

const newPath = ["A", "B", "C"];

function updateNodePaths(node) {
  // 克隆节点避免修改原对象
  const cloned = { ...node };
  if (cloned.id) {
    cloned.path = [...newPath, ...cloned.path];
  }
  // 递归处理子节点数组
  if (cloned.children?.length) {
    cloned.children = cloned.children.map(updateNodePaths);
  }
  return cloned;
}

const updatedObj = updateNodePaths(obj);

内容的提问来源于stack exchange,提问作者Thidasa Pankaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:33:23