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

为什么我的Lodash cloneDeepWith方法仅执行一次?

解决Lodash cloneDeepWith修改嵌套对象所有id的问题

你代码里的问题主要有两个:

  1. 逻辑范围错误:你把handleChangeIds作为cloneDeepWith的自定义函数,但这个函数只在当前节点等于sections时才处理,大部分节点都被直接跳过了。
  2. 递归中断:在自定义函数里返回修改后的对象后,Lodash会停止递归处理这个对象的子属性,所以只有第一个匹配的id被修改,嵌套的id没被处理。

下面给你两种可行的解决方案:

方案一:先深拷贝,再递归遍历修改所有id

这种方法逻辑简单直观,完全避免cloneDeepWith的递归陷阱,也不会修改原数据:

// 假设你的id生成函数是这个
const generateObjectId = () => {
  return Math.random().toString(36).slice(2, 10);
};

const cloneAndUpdateAllIds = (targetObj) => {
  // 先深拷贝整个对象,和原数据彻底隔离
  const cloned = cloneDeep(targetObj);

  // 递归遍历所有节点修改id
  const updateIds = (item) => {
    if (!item || typeof item !== 'object') return;
    
    // 检查当前节点是否有id属性,有就修改
    if (Object.hasOwn(item, 'id')) {
      item.id = generateObjectId();
    }

    // 递归处理所有子节点
    Object.values(item).forEach(updateIds);
  };

  updateIds(cloned);
  return cloned;
};

const DuplicateSection = () => {
  console.log('Original Store', form);
  const store = cloneAndUpdateAllIds(form);
  console.log('Modified', store);
};

方案二:正确使用cloneDeepWith(不推荐,容易踩坑)

如果一定要用cloneDeepWith,需要确保修改id后仍让Lodash继续递归子属性。核心是手动处理递归,避免中断:

const DuplicateSection = () => {
  console.log('Original Store', form);
  const store = cloneDeepWith(form, (value) => {
    // 只处理有id属性的对象
    if (value && Object.hasOwn(value, 'id')) {
      const cloned = { ...value };
      cloned.id = generateObjectId();
      // 手动递归处理子属性,避免Lodash中断递归
      return cloneDeepWith(cloned, arguments.callee);
    }
  });
  console.log('Modified', store);
};

显然方案一更简洁可靠,推荐使用第一种方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:25:51