在JavaScript中如何访问暂未存在的嵌套对象


Posted in Javascript onJune 18, 2019

前言

JavaScript 是个很神奇的东西。但是 JavaScript中的一些东西确实很奇怪,让人摸不着头脑。其中之一就是当你试图访问嵌套对象时,会遇到这个错误

Cannot read property 'foo' of undefined

在大多数情况下,处理嵌套的对象,通常我们需要安全地访问最内层嵌套的值。 来个粟子:

const user = {
  id: 101,
  email: 'jack@dev.com',
  personalInfo: {
    name: 'Jack',
    address: {
      line1: 'westwish st',
      line2: 'washmasher',
      city: 'wallas',
      state: 'WX'
    }
  }
}

当我们要访问user里面的name及city时,我们会这样写。

const name = user.personalInfo.name;
const userCity = user.personalInfo.address.city;

这是简单而直接的。

但是,由于某种原因,user 中的 personal不可用,对象结构将是这样的:

const user = {
  id: 101,
  email: 'jack@dev.com'
}

现在,如果你在试着访问 name ,将会得到一个 Cannot read property 'name' of undefined 的错误。

const name = user.personalInfo.name; // Cannot read property 'name' of undefined

这是因为我们试图访问对象中不在的 key 为 name 的属性。

大多数开发人员处理这种情况的常用方法如下,

const name = user && user.personalInfo ? user.personalInfo.name : null;

如果你的嵌套结构很简单,这是可以的,但是如果数据嵌套五或六层深,那么你的代码就会看起很混乱:

let city;
if (
  data && data.user && data.user.personalInfo &&
  data.user.personalInfo.addressDetails &&
  data.user.personalInfo.addressDetails.primaryAddress
  ) {
  city = data.user.personalInfo.addressDetails.primaryAddress;
}

有一些技巧可以处理这种混乱的对象结构。

Oliver Steele的嵌套对象访问模式

这是我个人的最爱,因为它使代码看起来干净简单。 我从 stackoverflow 中选择了这种风格,一旦你理解它是如何工作的,它就非常吸引人了。

const name = ((user || {}).personalInfo || {}).name;

使用这种表示法,永远不会遇到无法读取未定义的属性“name”。做法是检查用户是否存在,如果不存在,就创建一个空对象,这样,下一个级别的键将始终从存在的对象访问。

不幸的是,你不能使用此技巧访问嵌套数组。

使用数组Reduce访问嵌套对象

Array reduce 方法非常强大,可用于安全地访问嵌套对象。

const getNestedObject = (nestedObj, pathArr) => {
  return pathArr.reduce((obj, key) =>
    (obj && obj[key] !== 'undefined') ? obj[key] : null, nestedObj);
}

// 将对象结构作为数组元素传入
const name = getNestedObject(user, ['personalInfo', 'name']);

// 要访问嵌套数组,只需将数组索引作为数组元素传入。.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// 这将从 addresses 中的第一层返回 city

Typy

如果你认为上面的方法太过非主流,那么可以使用 Typy库。除了安全访问嵌套对象之外,它还可以做很多很棒的事情。

如果使用Typy,代码将如下所示

import t from 'typy';

const name = t(user, 'personalInfo.name').safeObject;
const city = t(user, 'personalInfo.addresses[0].city').safeObject;
// address is an array

这里还有一些其他的库,如 Lodash 和 Ramda,可以做到这一点。但是在轻量级前端项目中,特别是如果你只需要这些库中的一两个方法时,最好选择另一个轻量级库,或者编写自己的库。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Javascript+XMLHttpRequest+asp.net无刷新读取数据库数据
Aug 09 Javascript
jquery 快速回到页首的方法
Dec 05 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
Apr 06 Javascript
js利用prototype调用Array的slice方法示例
Jun 09 Javascript
js图片卷帘门导航菜单特效代码分享
Sep 10 Javascript
JavaScript中的对象继承关系
Aug 01 Javascript
javaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序整理总结
Oct 10 Javascript
webpack进阶——缓存与独立打包的用法
Aug 02 Javascript
总结js中的一些兼容性易错的问题
Dec 18 Javascript
vue实现全匹配搜索列表内容
Sep 26 Javascript
判断JavaScript中的两个变量是否相等的操作符
Dec 21 Javascript
浅谈vue 组件中的setInterval方法和window的不同
Jul 30 Javascript
用Vue.js在浏览器中实现裁剪图像功能
Jun 18 #Javascript
JS删除String里某个字符的方法
Jan 06 #Javascript
简单了解Javscript中兄弟ifream的方法调用
Jun 17 #Javascript
vue中typescript装饰器的使用方法超实用教程
Jun 17 #Javascript
简单学习5种处理Vue.js异常的方法
Jun 17 #Javascript
js/jQuery实现全选效果
Jun 17 #jQuery
解决微信浏览器缓存站点入口文件(IIS部署Vue项目)
Jun 17 #Javascript
You might like
PHP utf-8编码问题,utf8编码,数据库乱码,页面显示输出乱码
2013/04/08 PHP
如何在PHP中使用正则表达式进行查找替换
2013/06/13 PHP
php防止恶意刷新与刷票的方法
2014/11/21 PHP
php获取用户浏览器版本的方法
2015/01/03 PHP
在网页中屏蔽快捷键
2006/09/06 Javascript
node.js中的fs.renameSync方法使用说明
2014/12/16 Javascript
详解Document.Cookie
2015/12/25 Javascript
js实现的页面矩阵图形变换特效
2016/01/26 Javascript
第二篇Bootstrap起步
2016/06/21 Javascript
JS实现动态增加和删除li标签行的实例代码
2016/10/16 Javascript
JS数字千分位格式化实现方法总结
2016/12/16 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
jQuery插件HighCharts实现的2D回归直线散点效果示例【附demo源码下载】
2017/03/09 Javascript
echarts饼图扇区添加点击事件的实例
2017/10/16 Javascript
swiper动态改变滑动内容的实现方法
2018/01/17 Javascript
vue+vuex+axios实现登录、注册页权限拦截
2018/03/09 Javascript
mpvue跳转页面及注意事项
2018/08/03 Javascript
JavaScript数组方法的错误使用例子
2018/09/13 Javascript
Angular请求防抖处理第一次请求失效问题
2019/05/17 Javascript
在Vue中使用HOC模式的实现
2020/08/23 Javascript
解决vue项目 build之后资源文件找不到的问题
2020/09/12 Javascript
[01:56]《DOTA2》中文配音CG
2013/04/22 DOTA
[00:32]DOTA2上海特级锦标赛 COL战队宣传片
2016/03/04 DOTA
[56:21]LGD vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python变量不能以数字打头详解
2016/07/06 Python
浅谈Tensorflow模型的保存与恢复加载
2018/04/26 Python
python版DDOS攻击脚本
2019/06/12 Python
python实现雪花飘落效果实例讲解
2019/06/18 Python
浅析PEP572: 海象运算符
2019/10/15 Python
使用tensorflow显示pb模型的所有网络结点方式
2020/01/23 Python
解决使用python print打印函数返回值多一个None的问题
2020/04/09 Python
python 最简单的实现适配器设计模式的示例
2020/06/30 Python
物业保安员岗位职责制度
2014/01/30 职场文书
法院先进个人事迹材料
2014/05/04 职场文书
Oracle更换为MySQL遇到的问题及解决
2021/05/21 Oracle
Redis特殊数据类型Geospatial地理空间
2022/06/01 Redis