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

如何创建对象的不可变递归映射工具函数?处理嵌套对象

实现支持深度嵌套的对象映射工具函数(类似数组map的对象版本)

嘿,我明白你想要的是一个能递归遍历嵌套对象、对每个键值对(包括叶子节点)应用自定义转换逻辑的工具函数,就像数组的map方法那样,但专门针对对象结构。我来一步步帮你实现它,还会适配你给出的示例场景。

核心思路

这个工具函数需要做到:

  • 递归遍历对象的所有层级,包括嵌套的子对象
  • 对每个叶子节点(值为非对象/非数组的键值对)应用你指定的转换函数
  • 保留原对象的嵌套结构,生成全新的不可变对象(不修改原对象)
  • 支持路径参数,让转换函数能获取当前节点在对象中的完整路径(这在你的示例场景中很有用,因为需要匹配dark对象中对应路径的值)

完整实现代码

// 深度映射对象的工具函数
function deepMapObject(obj, fn, currentPath = []) {
  // 处理叶子节点(非对象/非数组的基本类型)
  if (typeof obj !== 'object' || obj === null) {
    // 给转换函数传递:当前键、当前值、父对象中的索引、完整路径
    return fn(currentPath.at(-1), obj, currentPath.length ? currentPath.slice(0, -1) : [], currentPath);
  }

  // 如果是数组,递归处理每个元素
  if (Array.isArray(obj)) {
    return obj.map((item, index) => 
      deepMapObject(item, fn, [...currentPath, index])
    );
  }

  // 处理普通对象
  const result = {};
  // 遍历对象的键值对,保持ES6+的插入顺序
  Object.entries(obj).forEach(([key, value], index) => {
    const newPath = [...currentPath, key];
    if (typeof value === 'object' && value !== null) {
      // 值是对象/数组,递归处理
      result[key] = deepMapObject(value, fn, newPath);
    } else {
      // 值是基本类型,应用转换函数
      result[key] = fn(key, value, index, newPath);
    }
  });

  return result;
}

// 辅助函数:根据路径获取嵌套对象中的值
function getNestedValue(obj, path) {
  return path.reduce((acc, key) => acc?.[key], obj);
}

适配你的示例场景

现在用你的示例数据来测试这个函数:

const light = { a: 'light-a', b: { b1: 'light-b1', b2: 'light-b2' } }
const dark = { a: 'dark-a', b: { b1: 'dark-b1', b2: 'dark-b2' } }

// 调用工具函数,生成light和dark的映射对象
const lightAndDark = deepMapObject(light, (key, value, index, path) => ({
  light: value,
  dark: getNestedValue(dark, path)
}));

console.log(lightAndDark);

输出结果

{
  a: { light: 'light-a', dark: 'dark-a' },
  b: {
    b1: { light: 'light-b1', dark: 'dark-b1' },
    b2: { light: 'light-b2', dark: 'dark-b2' }
  }
}

完全符合你期望的输出!

函数细节解释

  1. 递归逻辑:函数会自动判断当前值是不是对象/数组,如果是就继续递归遍历,直到遇到基本类型的叶子节点。
  2. 路径传递:currentPath参数会记录当前节点在整个对象中的完整路径,这样转换函数可以轻松获取其他对象中对应位置的值(比如示例中的dark对象)。
  3. 不可变性:函数始终创建新对象/数组,不会修改原对象,保证了数据的不可变性。
  4. 数组支持:额外添加了数组的处理逻辑,让函数也能适配数组嵌套的场景。

灵活扩展

你可以根据自己的需求修改转换函数,比如:

  • 修改键名:返回一个新的键值对(需要调整函数逻辑,比如让fn返回{newKey: newValue})
  • 对非叶子节点也应用转换:只需要调整递归逻辑,在处理对象时也调用fn即可
  • 过滤某些键:在遍历过程中添加条件判断,跳过不需要处理的键

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:12:37