如何创建对象的不可变递归映射工具函数?处理嵌套对象
实现支持深度嵌套的对象映射工具函数(类似数组
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' } } }
完全符合你期望的输出!
函数细节解释
- 递归逻辑:函数会自动判断当前值是不是对象/数组,如果是就继续递归遍历,直到遇到基本类型的叶子节点。
- 路径传递:
currentPath参数会记录当前节点在整个对象中的完整路径,这样转换函数可以轻松获取其他对象中对应位置的值(比如示例中的dark对象)。 - 不可变性:函数始终创建新对象/数组,不会修改原对象,保证了数据的不可变性。
- 数组支持:额外添加了数组的处理逻辑,让函数也能适配数组嵌套的场景。
灵活扩展
你可以根据自己的需求修改转换函数,比如:
- 修改键名:返回一个新的键值对(需要调整函数逻辑,比如让fn返回
{newKey: newValue}) - 对非叶子节点也应用转换:只需要调整递归逻辑,在处理对象时也调用fn即可
- 过滤某些键:在遍历过程中添加条件判断,跳过不需要处理的键
内容的提问来源于stack exchange,提问作者Stephen Koo
相关产品推荐
相关产品推荐

