如何实现支持任意路径的JSON对象值修改通用函数?
通用实现:通过路径修改JSON对象值的函数
嘿,我完全懂你现在的痛点——那种硬编码路径长度的写法太死板了,路径稍微深一点就直接抛错,完全没法应对复杂的场景。别担心,咱们来搞一个通用的实现方案,不管你的路径有多长,都能轻松搞定!
先聊聊原有代码的问题
你原来的写法是通过判断path.length等于1、2、3来处理不同深度的路径,超过就抛出"too lazy"的错误,这种方式的局限性太明显了:
- 没法处理任意深度的路径,扩展性极差
- 代码冗余,每加一个深度就要多写一个
if判断 - 遇到不存在的中间节点会直接报错,容错性差
方案1:迭代式实现(推荐,性能更优)
这种方式通过循环遍历路径的每一段,逐步深入到目标节点,最后完成赋值。逻辑清晰,没有递归调用栈的开销,适合大多数场景。
// 假设config是全局的根对象 var config = {}; var setConfigItem = function(path, value) { let current = config; // 遍历路径的前n-1个节点(最后一个是要赋值的键) for (let i = 0; i < path.length - 1; i++) { const key = path[i]; // 如果当前节点不存在,或者不是对象/数组,就创建一个空对象 // 如果你想支持数组,可以把这里改成判断是否是数组或者对象,按需调整 if (!current[key] || typeof current[key] !== 'object') { current[key] = {}; } // 移动到下一级节点 current = current[key]; } // 给最后一个键赋值 current[path[path.length - 1]] = value; };
用法示例
// 调用后,config会变成 { node1: { nodeA: { value1A: 1234 } } } setConfigItem(['node1','nodeA','value1A'], 1234); // 支持更长的路径 setConfigItem(['a','b','c','d','e'], 'hello');
可选优化:仅修改已存在的路径
如果你不想自动创建不存在的中间节点(比如只允许修改已有配置),可以加个判断抛出错误:
var setConfigItem = function(path, value) { let current = config; for (let i = 0; i < path.length - 1; i++) { const key = path[i]; if (!current[key] || typeof current[key] !== 'object') { throw new Error(`路径片段 "${key}" 不存在或不是对象`); } current = current[key]; } current[path[path.length - 1]] = value; };
方案2:递归式实现(代码更简洁)
如果你更喜欢递归的写法,也可以用这种方式,代码更紧凑,逻辑同样清晰:
var config = {}; var setConfigItem = function(path, value, current = config) { // 路径只剩最后一个元素时,直接赋值 if (path.length === 1) { current[path[0]] = value; return; } // 解构出第一个路径片段和剩余路径 const [firstKey, ...restPath] = path; // 不存在则创建节点 if (!current[firstKey] || typeof current[firstKey] !== 'object') { current[firstKey] = {}; } // 递归处理剩余路径 setConfigItem(restPath, value, current[firstKey]); };
总结
- 迭代式:性能更好,适合处理极深的路径(避免递归栈溢出),逻辑直观
- 递归式:代码更简洁,可读性强,适合一般深度的路径
两种方案都能完美替代你原来的硬编码写法,支持任意长度的路径,扩展性拉满!
内容的提问来源于stack exchange,提问作者no one special
相关产品推荐
相关产品推荐

