如何编写JavaScript递归函数在嵌套对象中按键值查找?
递归搜索嵌套对象的键值对问题
我尝试编写递归函数,用来在嵌套对象中按键和值搜索,但始终无法实现,试过多个示例都不行,求帮忙解决。
我的目标对象如下:
var menuObj = { "mainmenu": [ { "id" : 72, "menu_id" :1 , "parent_id" : 0, "href" : "{\"routeName\":\"post-page\",\"routeParams\":{\"slug\":\"algemene-voorwaarden\"}}", "permission" : null, "hierarchie" : 0, "blank" : 0, "status" : "published", "label" : "Algemene Voorwaarden", "children":[] }, { "id" : 73, "menu_id" : 1, "parent_id" : 0, "href" : "{\"routeName\":\"post-page\",\"routeParams\":{\"slug\":\"privacy\"}}", "permission" : null, "hierarchie" : 1, "blank" : 0, "status" : "published", "label" : "Privacy", "children" : [ { "id" : 101, "menu_id" : 1, "parent_id" : 73, "href" : "{\"routeName\":\"blog\"}", "permission" : null, "hierarchie" : 2, "blank" : 0, "status" : "published", "label" : "blog", "children" : [ { "id" : 102, "menu_id" : 1, "parent_id" : 101, "href" : "{\"routeName\":\"blog\",\"routeParams\":{\"category_slug\":\"categorie-2\"}}", "permission" : null, "hierarchie" : 3, "blank" : 0, "status" : "published", "label" : "Categorie 2", "children" : [] } ] } ] } ] };
我需要一个这样的函数:
function fnFindKeyValuePair(obj, key, value) { // 返回true/false/null/undefined 或者匹配的对象 }
搜索示例:
fnFindKeyValuePair(menuObj['mainmenu'], 'href', "{\"routeName\":\"blog\"}")
预期结果:返回真值或者对应的匹配对象:
{ "id" : 101, "menu_id" : 1, "parent_id" : 73, "href" : "{\"routeName\":\"blog\"}", "permission" : null, "hierarchie" : 2, "blank" : 0, "status" : "published", "label" : "blog", "children" : [ { "id" : 102, "menu_id" : 1, "parent_id" : 101, "href" : "{\"routeName\":\"blog\",\"routeParams\":{\"category_slug\":\"categorie-2\"}}", "permission" : null, "hierarchie" : 3, "blank" : 0, "status" : "published", "label" : "Categorie 2", "children" : [] } ] }
解决方案
以下是可以实现需求的递归函数,支持数组和对象的嵌套结构,找到匹配项后立即返回:
function fnFindKeyValuePair(obj, key, value) { // 处理数组:遍历每个元素递归搜索 if (Array.isArray(obj)) { for (const item of obj) { const result = fnFindKeyValuePair(item, key, value); if (result) return result; } return null; } // 处理对象:先检查当前对象是否匹配 if (typeof obj === 'object' && obj !== null) { if (obj[key] === value) return obj; // 遍历对象属性,递归搜索嵌套结构 for (const prop in obj) { if (obj.hasOwnProperty(prop)) { const result = fnFindKeyValuePair(obj[prop], key, value); if (result) return result; } } } // 非对象/数组或未找到匹配项 return null; }
函数说明:
- 优先处理数组输入,遍历数组元素逐个递归搜索
- 若输入是对象,先检查当前对象的目标键值是否匹配,匹配则直接返回当前对象
- 当前对象不匹配时,遍历其所有自有属性,递归搜索嵌套的对象或数组
- 未找到匹配项时返回
null
使用验证:
执行以下代码即可得到预期结果:
const matchedObj = fnFindKeyValuePair(menuObj['mainmenu'], 'href', "{\"routeName\":\"blog\"}"); console.log(matchedObj);
额外优化(针对JSON字符串匹配):
如果href这类字段是JSON字符串,建议解析成对象后再比较,避免因字符串格式细节(如空格、转义差异)导致匹配失败。优化后的函数如下:
function fnFindKeyValuePair(obj, key, value, parseJson = false) { if (Array.isArray(obj)) { for (const item of obj) { const result = fnFindKeyValuePair(item, key, value, parseJson); if (result) return result; } return null; } if (typeof obj === 'object' && obj !== null) { let currentVal = obj[key]; let targetVal = value; // 开启JSON解析时,尝试解析字符串为对象 if (parseJson && typeof currentVal === 'string' && typeof targetVal === 'string') { try { currentVal = JSON.parse(currentVal); targetVal = JSON.parse(targetVal); } catch (e) { // 解析失败则保留原字符串比较 } } // 使用JSON.stringify统一比较对象或字符串 if (JSON.stringify(currentVal) === JSON.stringify(targetVal)) { return obj; } for (const prop in obj) { if (obj.hasOwnProperty(prop)) { const result = fnFindKeyValuePair(obj[prop], key, value, parseJson); if (result) return result; } } } return null; }
使用优化版函数时,传入true开启JSON解析匹配:
const matchedObj = fnFindKeyValuePair(menuObj['mainmenu'], 'href', '{"routeName":"blog"}', true);
内容的提问来源于stack exchange,提问作者poashoas
相关产品推荐
相关产品推荐

