深度探索:如何安全检查多层嵌套对象属性是否存在?

更新日期: 2025-06-08阅读: 40标签: 属性

在 JavaScript 开发中,处理类似 user.address.city 这样的深层嵌套属性是常见需求,但直接访问可能导致灾难性的 Cannot read property 'city' of undefined 错误。本文将分享几种专业级解决方案,助你优雅避开这些陷阱。


 解决方案一:防御式条件检查(传统可靠)

通过逐层显式验证确保每层对象存在:

function getCity(user) {
  if (user && 
      user.address && 
      typeof user.address === 'object' && 
      'city' in user.address) {
    return user.address.city;
  }
  return '未知地区';
}

// 测试用例
const user1 = { address: { city: '北京' } };
const user2 = { address: null };
const user3 = undefined;

console.log(getCity(user1)); // "北京"
console.log(getCity(user2)); // "未知地区"
console.log(getCity(user3)); // "未知地区"

优点

  • 兼容所有 JavaScript 环境

  • 精确控制每层验证逻辑

  • 可添加额外类型检查(如 typeof === 'object')

缺点

  • 嵌套过深时代码冗长

  • 重复性代码增加维护成本


解决方案二:可选链操作符(现代首选)

ES2020 引入的可选链操作符(?.)是当前最优雅的解决方案:

// 安全访问嵌套属性
const city = user?.address?.city;

// 配合空值合并设置默认值
const safeCity = user?.address?.city ?? '未知地区';

// 安全方法调用
const street = user?.getAddress?.().street;

关键特性

  • 遇到 null 或 undefined 立即停止并返回 undefined

  • 可与函数调用结合:obj.method?.()

  • 支持动态属性:obj?.[dynamicKey]

浏览器兼容性

  • 现代浏览器和 Node.js 14+ 原生支持

  • 旧环境通过 babel 插件 @babel/plugin-proposal-optional-chaining 转译


解决方案三:工具函数封装

创建可复用的安全访问函数:

function deepGet(obj, path, defaultValue = null) {
  // 路径格式处理:'a.b.c' 或 ['a', 'b', 'c']
  const keys = Array.isArray(path) ? path : path.split('.');
  
  let current = obj;
  for (const key of keys) {
    // 遇到 null/undefined 提前终止
    if (current?.[key] === undefined) return defaultValue;
    current = current[key];
  }
  
  return current ?? defaultValue;
}

// 使用示例
const location = deepGet(user, 'address.location', {});
const postCode = deepGet(user, ['address', 'postalCode'], '000000');

增强功能方向

  1. 支持数组索引:'contacts[0].phone'

  2. 添加类型校验:确保末级值为特定类型

  3. 错误追踪:记录访问失败路径


解决方案四:使用 Lodash 等工具库

对已使用 Lodash 的项目,_.get() 是最安全便捷的选择:

import _ from 'lodash';

// 基本使用
const city = _.get(user, 'address.city', '默认城市');

// 支持复杂路径
const firstFriend = _.get(user, 'friends[0].name', '无好友');

// 存在性检查(不取值)
const hasAddress = _.has(user, 'address.coordinates.latitude');

对比原生优势

  • 支持数组索引和特殊字符路径

  • 经过严格测试的边界情况处理

  • 统一代码风格降低认知成本


特殊场景处理技巧

Map/Set 集合检查

// Map 类型检查
const map = new Map([['user', { name: 'Alice' }]]);
const hasUser = map.has('user') && 'name' in map.get('user');

类数组对象处理

// 安全访问 dom 集合
const firstChild = document.querySelectorAll('div')?.[0];

可选链与类型守卫结合

interface Address {
city?: string;
location?: { lat: number; lng: number };
}

// TypeScript 中确保类型安全
const coordinates = (user.address as Address)?.location;


方案选择指南

场景推荐方案原因
简单项目/无需转译防御式条件检查零依赖、最大兼容性
现代框架/ES2020+环境可选链操作符代码简洁、表达力强
大型企业级应用Lodash 工具库统一维护、边界处理完善
特殊数据结构(Map/Set)专用检查方法符合特定api行为


最佳实践总结

优先使用可选链:现代项目中首选 ?. 语法,配合 ?? 设置默认值

防御性编程:对第三方数据源始终保持 "不信任" 验证原则

深度检查分离:属性访问与业务逻辑分离,避免多层嵌套表达式

TypeScript强化:结合类型守卫确保编译时安全:

function isAddress(obj: any): obj is Address {
return obj && typeof obj === 'object';
}

if (isAddress(user.address)) {
// 此处可安全访问 address 所有属性
}

通过合理运用这些技术,不仅能彻底消除恼人的 undefined 访问错误,更能构建出健壮的前端数据访问层。随着可选链操作符的普及,2023年全球使用率已超过92%(来源:MDN 兼容性数据),是现代Web开发的必备技能。

链接: https://fly63.com/article/detial/12727

display: none;与visibility: hidden;的区别

display:none;会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility: hidden;不会让元素从渲染树消失,渲染师元素继续占据空间,只是内容不可见,display: none;是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;

属性设置百分比时的计算参考汇总

元素宽高width,min-width,max-width等元素宽度设置百分比,以包含块的宽度为标准进行计算;height,min-height,max-height等元素宽度设置百分比,以包含块的高度为标准进行计算;

readonly与disabled的区别

readonly 只对 <input> 和 <textarea> 标签有效;disabled 对所有表单元素都有效, 包括:<input>, <textarea>, <button>, <label>, <option>, <select>等

css的overflow属性

事实上我挺长一段时间都没弄清楚overflow:scroll与overflow:auto的差别,今天测试了一下,总算是明白了。visible: 不剪切内容。hidden: 将超出对象尺寸的内容进行裁剪,将不出现滚动条。scroll: 将超出对象尺寸的内容进行裁剪,并以滚动条的方式显示超出的内容。

Vue Prop属性功能与用法实例

这篇文章主要介绍了Vue Prop属性功能与用法,结合实例形式较为详细的分析了vue.js中Prop属性的功能、原理、使用方法及相关操作注意事项,写的十分的全面细致,具有一定的参考价值

深入剖析z-index属性

层叠顺序的大小比较;层叠顺序级别高的元素覆盖级别低的元素。首先要注意,z-index:auto 虽然可以看作z-index:0 ,但是这仅仅是在层叠顺序的比较上;从层叠上下文上讲,二者有本质差别:auto 不会创建层叠上下文,z-index:0 会创建层叠上下文。

Vue.js-计算属性和class与style绑定

所有的计算属性都以函数的形式写在Vue实例中的computed选项内,最终返回计算后的结果。在一个计算属性中可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果即可。

css属性分类介绍

CSS分类目录 文本/字体/颜色 文本相关 字体相关 颜色相关 背景相关 大小/布局 大小属性 margin 外边距 padding 内边距 border 边框 position 定位 列表/表格 多列属性 可伸缩框属性 列表属性 Grid属性 Table属性 动画属性 Animation 动画属性 Transition 过渡属性

css中word-wrap white-space word-break textoverflow的使用

word-wrap正常来说,在一行文本中,如果出现这一行已经放不下的单词,浏览器会自动将该文字转入下一行。white-space规定段落中的文本不进行换行。

css使用到的border边框属性

border 在一个声明中设置所有的边框属性。 border-bottom在一个声明中设置所有的下边框属性。border-bottom-color设置下边框的颜色。border-bottom-style设置下边框的样式。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!