从JSON数据树获取对象的函数复用问题及修复方案求解
优化方案
问题根因
原函数的核心问题是将匹配结果变量objFound定义在全局作用域,函数执行完成后该变量不会自动重置,多次调用会复用第一次执行后的残留值,导致后续查询结果异常。
方案1:封装状态变量到函数作用域(兼容原有逻辑)
将递归逻辑封装到函数内部的子函数中,每次调用外层函数都会重新初始化objFound变量,避免全局污染,逻辑和原有写法基本一致,改动成本最低:
function getObjFromValue(obj, prop, val) { let objFound = null; // 内层递归函数 function deepSearch(currentObj) { Object.keys(currentObj).forEach((key) => { if (objFound !== null) return; if (key === prop && currentObj[key] === val) { objFound = currentObj; return; } if (typeof currentObj[key] === 'object' && currentObj[key] !== null) { deepSearch(currentObj[key]); } }); } deepSearch(obj); return objFound; }
注:额外加了
currentObj[key] !== null的判断,避免typeof null === 'object'的JS历史问题导致报错。
方案2:无状态变量的递归实现(性能更优)
直接利用递归返回值传递匹配结果,一旦找到匹配项就逐层提前返回,不需要额外的状态变量,也不会遍历剩余节点,性能更好:
function getObjFromValue(obj, prop, val) { // 先判断当前层是否匹配 if (obj.hasOwnProperty(prop) && obj[prop] === val) { return obj; } // 遍历所有属性递归查找 for (const key of Object.keys(obj)) { const currentVal = obj[key]; if (typeof currentVal === 'object' && currentVal !== null) { const matchResult = getObjFromValue(currentVal, prop, val); if (matchResult !== null) { return matchResult; } } } // 全节点未匹配返回null return null; }
注:这里替换
forEach为for...of循环,是因为forEach无法通过return直接终止整个循环,用for循环可以在匹配到结果后立刻终止遍历,进一步提升性能。
内容的提问来源于stack exchange,提问作者Dexter
相关产品推荐
相关产品推荐

