在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 相关文章推荐
JQuery 遮罩层实现(mask)实现代码
Jan 09 Javascript
jQuery的写法不同导致的兼容性问题的解决方法
Jul 29 Javascript
js动态设置div的值下例子
Oct 29 Javascript
JS循环遍历JSON数据的方法
Jul 08 Javascript
jQuery蓝色风格滑动导航栏代码分享
Aug 19 Javascript
微信小程序 摇一摇抽奖简单实例实现代码
Jan 09 Javascript
Bootstrap按钮组简单实现代码
Mar 06 Javascript
详解利用 Express 托管静态文件的方法
Sep 18 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(下)
Apr 18 Javascript
Vue实现PC端靠边悬浮球的代码
May 09 Javascript
JS事件循环机制event loop宏任务微任务原理解析
Aug 04 Javascript
JS实现悬浮球只在一侧滑动并且是横屏状态下
Aug 19 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根据两点间的经纬度计算距离
2014/10/31 PHP
PHP中使用substr()截取字符串出现中文乱码问题该怎么办
2015/10/21 PHP
php面向对象值单例模式
2016/05/03 PHP
php实现根据身份证获取精准年龄
2020/02/26 PHP
JavaScript面向对象编程
2008/03/02 Javascript
jquery.qrcode在线生成二维码使用示例
2013/08/21 Javascript
window.print打印指定div实例代码
2013/12/13 Javascript
JS+CSS实现仿支付宝菜单选中效果代码
2015/09/25 Javascript
JS 清除字符串数组中,重复元素的实现方法
2016/05/24 Javascript
js实现为a标签添加事件的方法(使用闭包循环)
2016/08/02 Javascript
js弹出窗口简单实现代码
2017/03/22 Javascript
Vue.js中轻松解决v-for执行出错的三个方案
2017/06/09 Javascript
深究AngularJS如何获取input的焦点(自定义指令)
2017/06/12 Javascript
ReactNative踩坑之配置调试端口的解决方法
2017/07/28 Javascript
javascript基于牛顿迭代法实现求浮点数的平方根【递归原理】
2017/09/28 Javascript
微信小程序实现刷脸登录
2018/05/25 Javascript
Vue-router 中hash模式和history模式的区别
2018/07/24 Javascript
vue实现word,pdf文件的导出功能
2018/07/31 Javascript
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
JS document内容及样式操作完整示例
2020/01/14 Javascript
javascript开发实现贪吃蛇游戏
2020/07/31 Javascript
[45:59]完美世界DOTA2联赛PWL S2 FTD vs GXR 第二场 11.22
2020/11/24 DOTA
遗传算法之Python实现代码
2017/10/10 Python
Django获取应用下的所有models的例子
2019/08/30 Python
Python bisect模块原理及常见实例
2020/06/17 Python
法国在线药房:1001Pharmacies
2021/03/07 全球购物
开放系统互连参考模型
2016/06/29 面试题
给定一个时间点,希望得到其他时间点
2013/11/07 面试题
素食餐饮项目创业计划书
2014/02/02 职场文书
禁毒宣传标语
2014/06/19 职场文书
销售顾问工作计划书
2014/09/15 职场文书
华山导游词
2015/02/03 职场文书
小学端午节活动总结
2015/02/11 职场文书
商场广播稿范文
2015/08/19 职场文书
vue如何实现关闭对话框后刷新列表
2022/04/08 Vue.js
HTML静态页面获取url参数和UserAgent的实现
2022/08/05 HTML / CSS