如何检查嵌套对象属性的有效性?含实现思路及代码示例
安全访问嵌套对象属性的解决方案
嘿,你的思路方向是对的——通过拆分路径逐层验证属性存在性确实能避免嵌套访问报错,但这里有几个关键问题需要先纠正,再给你完善后的实现:
先纠正一个核心误区
你不能直接把 obj.food[drinks.category][drinkID].value 作为参数传给 validObj,因为如果中间任何一个属性(比如food不存在,或者drinks.category对应的属性名不存在),这行代码在调用函数之前就会抛出 Cannot read properties of undefined 错误,根本进不了函数内部。而且你代码里的 let objPathStr = obj 也不对,obj 是对象本身,不是它的访问路径字符串,对象不会自带路径信息。
完善后的实现思路
我们需要调整函数的设计:让函数接收目标对象和路径描述(数组或字符串),而不是传已经在执行访问的表达式。这样就能提前在函数内部逐层检查每个属性是否存在。
方案1:属性存在性验证函数
这个函数会检查路径上的所有属性是否都存在,返回布尔值:
function isValidNestedProp(obj, path) { let current = obj; // 如果传入的是路径字符串,先转换成数组(支持两种格式:"food.drinks.value" 或 "food[drinks][value]") if (typeof path === 'string') { path = path.replace(/\[([^\]]+)\]/g, '.$1').split('.'); } // 逐层遍历路径,验证属性存在性 for (const key of path) { // 检查当前层级是否存在,且拥有该属性(避免原型链上的属性干扰) if (!current || !current.hasOwnProperty(key)) { return false; } current = current[key]; } return true; }
针对你的场景,因为 drinks.category 和 drinkID 是变量(它们的值才是实际的属性名),所以路径数组要这样传:
// 构建路径数组,把变量作为元素传入 const targetPath = ['food', drinks.category, drinkID, 'value']; // 验证属性是否可安全访问 const canAccess = isValidNestedProp(obj, targetPath); if (canAccess) { // 验证通过后再安全访问 const value = obj.food[drinks.category][drinkID].value; // 后续处理逻辑 }
方案2:直接安全获取值的函数
如果你的需求是直接获取值(不存在时返回默认值),可以写一个更实用的函数,不用先验证再访问:
function getNestedProp(obj, path, defaultValue = undefined) { let current = obj; if (typeof path === 'string') { path = path.replace(/\[([^\]]+)\]/g, '.$1').split('.'); } for (const key of path) { if (!current || !current.hasOwnProperty(key)) { return defaultValue; } current = current[key]; } return current; } // 使用方式:传入对象、路径数组和默认值 const value = getNestedProp(obj, ['food', drinks.category, drinkID, 'value'], null); // 如果路径上任何属性不存在,value就会是你设置的默认值null,不会报错
方案3:现代JS的简化写法(可选链操作符)
如果你用的是ES2020及以上的环境,可选链操作符 ?. 可以让你一行代码搞定,不用写自定义函数:
// 直接安全访问,不存在的话返回undefined const value = obj?.food?.[drinks.category]?.[drinkID]?.value; // 如果要验证是否所有属性都存在(注意:如果value本身就是undefined会误判,需要结合实际场景) const isAccessible = obj?.food?.[drinks.category]?.[drinkID] !== undefined;
总结
- 不要直接传
obj.food[drinks.category][drinkID].value给验证函数,会提前报错 - 自定义函数适合需要严格验证属性存在性(排除原型链属性)的场景
- 可选链是最简洁的方案,适合大部分现代项目
内容的提问来源于stack exchange,提问作者RoyBarOn
相关产品推荐
相关产品推荐

