如何根据数组值获取对象键?含嵌套对象场景解决方案
问题描述
我编写了如下JavaScript代码,尝试通过getObjKey函数根据值获取对象的键:
function getObjKey(obj, value) { return Object.keys(obj).find(key => obj[key] === value); } const obj = {city1: ['Santiago','Germany'], city2: 'Chicago'}; console.log(getObjKey(obj, ['Santiago','Germany']));
希望获取数组['Santiago','Germany']对应的键city1,但执行上述代码无法实现;而传入字符串值'Chicago'时,能正常返回对应键city2。
后续对象结构更新为嵌套形式:
const obj = { city1: ['Santiago','Germany'], city2: 'Chicago', level1: {level2 : [{level3:'chennai'},{level4:'madurai'}]} };
当传入数组[{level3:'chennai'},{level4:'madurai'}]作为参数时,也无法获取其对应的键level2。请问该如何解决这两个问题?
解决方案
核心原因
JavaScript中,原始值(字符串、数字等)按值比较,而引用值(数组、对象)按内存引用地址比较。你传入的目标数组/对象,和对象中存储的对应值虽然内容一致,但属于不同的内存引用,因此===判断会返回false,导致无法匹配。
1. 平级对象的解决方案
需要自定义深度比较函数,判断两个值的内容是否完全一致,再修改查找函数使用该比较逻辑:
// 深度比较两个值的内容是否相等 function isDeepEqual(a, b) { // 原始值或同一引用直接返回true if (a === b) return true; // 一方为null/undefined直接返回false if (a == null || b == null) return false; // 类型不同返回false if (typeof a !== typeof b) return false; // 数组比较:长度一致且每个元素深度相等 if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; return a.every((item, idx) => isDeepEqual(item, b[idx])); } // 对象比较:键数量一致且每个键值对深度相等 if (typeof a === 'object' && typeof b === 'object') { const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; return keysA.every(key => isDeepEqual(a[key], b[key])); } // 其他不匹配情况 return false; } // 修改后的键查找函数 function getObjKey(obj, targetValue) { return Object.keys(obj).find(key => isDeepEqual(obj[key], targetValue)); } // 测试 const flatObj = {city1: ['Santiago','Germany'], city2: 'Chicago'}; console.log(getObjKey(flatObj, ['Santiago','Germany'])); // 输出: city1 console.log(getObjKey(flatObj, 'Chicago')); // 输出: city2
2. 嵌套对象的解决方案
如果需要遍历多层嵌套的对象结构,需要在查找函数中加入递归逻辑,遍历所有层级的键值对:
// 递归遍历嵌套对象,根据值查找对应键 function getNestedObjKey(obj, targetValue) { for (const key in obj) { // 只遍历对象自身的属性,排除原型链属性 if (!obj.hasOwnProperty(key)) continue; const currentValue = obj[key]; // 当前值匹配则返回键 if (isDeepEqual(currentValue, targetValue)) { return key; } // 如果当前值是对象/数组,递归进入下一层查找 if ((typeof currentValue === 'object' && currentValue != null) || Array.isArray(currentValue)) { const nestedKey = getNestedObjKey(currentValue, targetValue); if (nestedKey) return nestedKey; } } // 未找到匹配值时返回null return null; } // 测试 const nestedObj = { city1: ['Santiago','Germany'], city2: 'Chicago', level1: {level2 : [{level3:'chennai'},{level4:'madurai'}]} }; console.log(getNestedObjKey(nestedObj, [{level3:'chennai'},{level4:'madurai'}])); // 输出: level2
注意事项
- 若对象中存在多个内容相同的目标值,函数会返回第一个匹配到的键。
- 上述深度比较函数未处理循环引用(如对象引用自身),如果你的数据存在这种场景,需要额外添加循环引用检测逻辑。
内容的提问来源于stack exchange,提问作者Aakash Pawan G P S
相关产品推荐
相关产品推荐

