JS递归查找嵌套对象数组中值失败问题排查与修复
修复嵌套对象/数组中查找目标值的递归函数问题
我编写了findInObj和findInArray两个递归函数,旨在从嵌套的对象与数组(即给定的HAYSTACK)中查找目标值(例如ldfzjeyfuvbkcjccztn,又称needle),找到则返回其父对象,否则返回false。尽管目标值存在于HAYSTACK中,但当前函数无法正常工作。我推测findInObj在遇到不含对象或数组的嵌套对象时会直接返回false,导致同一层级的其他属性未被检查。请帮忙修复这两个函数,使其能在任意层级找到目标值。
HAYSTACK
{ "slide1": { "uid": 1672503300574, "zones": [ { "imgData": { "name": "Universe.png", "type": "image/png" }, "uid": 1648468065257, "styles": { "height": "327px", "width": "421px" }, "canvasElementType": "photo" }, { "imgData": { "name": "water_treatment_plant.png", "type": "image/png" }, "uid": 1648468065580, "styles": { "height": "517px", "width": "536px" }, "canvasElementType": "photo" } ], "headings": [ { "title": "First TextBox", "titleStyles": { "height": "92px", "width": "498px" }, "uid": "ldfzjesz45rh6v5lvoi" }, { "title": "Secoooond TextBox", "titleStyles": { "height": "116px", "width": "282px" }, "uid": "ldfzjeub9zix7yuajmj" }, { "title": "Infinity", "titleStyles": { "height": "97px", "width": "315px" }, "uid": "ldfzjeyfuvbkcjccztn" } ], "slideWrapperStyles": {}, "duration": 5000 } }
Func - Find In OBJECT
export function findInObj(obj, needle) { for(var key in obj) { var val = obj[key] //if ITEM is an Array if(val instanceof Array) { let retVal = findInArray(val, needle, obj) if(retVal) return retVal } //If ITEM is an Object if(val instanceof Object && !(val instanceof Array)) { return findInObj(val, needle) } else { //Neither Object or Array if(val == needle) { return obj } } } //Return `false` when the no item matches return false }
Func - Find In ARRAY
export function findInArray(arr, needle, obj) { console.log("arr", arr); for(var item of arr) { //if item is an array if(item instanceof Array) { let retVal = findInArray(item, needle, obj) if(retVal) return retVal } //If Item is an Object if(item instanceof Object && !(item instanceof Array)) { let retVal = findInObj(item, needle) if(retVal) return retVal } //If Item is `anything`other than Array/Object if(item == needle) { return obj } } return false }
问题分析与修复方案
核心问题
findInObj函数中,遍历到子对象时直接用return findInObj(val, needle),若该子对象未找到目标值,函数会直接返回false,终止当前对象剩余属性的遍历,导致同一层级其他属性被忽略,这就是目标值存在却找不到的原因。
修复后的函数
修复后的findInObj
export function findInObj(obj, needle) { for(var key in obj) { var val = obj[key] // 处理数组 if(Array.isArray(val)) { let retVal = findInArray(val, needle, obj) if(retVal) return retVal } // 处理对象(排除数组和null) if(typeof val === 'object' && val !== null && !Array.isArray(val)) { let retVal = findInObj(val, needle) if(retVal) return retVal } else { // 处理基础类型值 if(val === needle) { return obj } } } return false }
修复后的findInArray
export function findInArray(arr, needle, parentObj) { for(var item of arr) { // 处理嵌套数组 if(Array.isArray(item)) { let retVal = findInArray(item, needle, parentObj) if(retVal) return retVal } // 处理数组中的对象 if(typeof item === 'object' && item !== null && !Array.isArray(item)) { let retVal = findInObj(item, needle) if(retVal) return retVal } // 处理数组中的基础类型值 if(item === needle) { return parentObj } } return false }
关键改进点
- 修复遍历逻辑:将
findInObj中直接返回子对象递归结果改为先接收返回值,仅找到目标时才返回,否则继续遍历当前对象的其他属性。 - 优化类型判断:用
Array.isArray()替代instanceof Array,类型判断更严谨;增加val !== null判断(因为typeof null === 'object')。 - 语义化变量:将
findInArray的第三个参数从obj改为parentObj,含义更清晰。
测试验证
调用findInObj(HAYSTACK, 'ldfzjeyfuvbkcjccztn'),会正确返回headings数组中的第三个对象:
{ "title": "Infinity", "titleStyles": { "height": "97px", "width": "315px" }, "uid": "ldfzjeyfuvbkcjccztn" }
内容的提问来源于stack exchange,提问作者dkjain
相关产品推荐
相关产品推荐

