在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实现动态增加删除表格行(兼容IE/FF)
Apr 02 Javascript
javaScript NameSpace 简单说明介绍
Jul 18 Javascript
利用JS解决ie6不支持max-width,max-height问题的方法
Jan 02 Javascript
javascript 终止函数执行操作
Feb 14 Javascript
javascript闭包的理解
Apr 01 Javascript
javascript实现选中复选框后相关输入框变灰不可用的方法
Aug 11 Javascript
JavaScript实现获取某个元素相邻兄弟节点的prev与next方法
Jan 25 Javascript
Angularjs结合Bootstrap制作的一个TODO List
Aug 18 Javascript
jQuery实现移动端手机商城购物车功能
Sep 24 Javascript
微信小程序注册60s倒计时功能 使用JS实现注册60s倒计时功能
Aug 16 Javascript
vue引入静态js文件的方法
Jun 20 Javascript
利用node.js开发cli的完整步骤
Dec 29 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
写一个用户在线显示的程序
2006/10/09 PHP
Laravel框架源码解析之反射的使用详解
2020/05/14 PHP
一个对于Array的简单扩展
2006/10/03 Javascript
js 新浪的一个图片播放图片轮换效果代码
2008/07/15 Javascript
javascript 获取元素位置的快速方法 getBoundingClientRect()
2009/11/26 Javascript
控制文字内容的显示与隐藏示例
2014/06/11 Javascript
JavaScript中的Math.sin()方法使用详解
2015/06/15 Javascript
.NET微信公众号开发之创建自定义菜单
2015/07/16 Javascript
jquery+html5烂漫爱心表白动画代码分享
2015/08/24 Javascript
不定义JQuery插件 不要说会JQuery
2016/03/07 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
bootstrap-wysiwyg结合ajax实现图片上传实时刷新功能
2016/05/27 Javascript
jQuery+CSS实现简单切换菜单示例
2016/07/27 Javascript
微信小程序 参数传递详解
2016/10/24 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
Vue在 Nuxt.js 中重定向 404 页面的方法
2019/04/23 Javascript
解决微信小程序云开发中获取数据库的内容为空的方法
2019/05/15 Javascript
Vue多环境代理配置方法思路详解
2019/06/21 Javascript
js实现简单掷骰子效果
2019/10/24 Javascript
es6函数中的作用域实例分析
2020/04/18 Javascript
[02:57]DOTA2英雄基础教程 风行者
2014/01/16 DOTA
[04:50]DOTA2亚洲邀请赛小组赛第四日 TOP10精彩集锦
2015/02/02 DOTA
[04:56]经典回顾:前Ehome 与 前LGD
2015/02/26 DOTA
Python群发邮件实例代码
2014/01/03 Python
使用Python处理BAM的方法
2018/09/28 Python
pandas 数据归一化以及行删除例程的方法
2018/11/10 Python
Python使用指定字符长度切分数据示例
2019/12/05 Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
2020/03/07 Python
Django 解决新建表删除后无法重新创建等问题
2020/05/21 Python
python 装饰器重要在哪
2021/02/14 Python
详解CSS3选择器:nth-child和:nth-of-type之间的差异
2017/09/18 HTML / CSS
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
乡镇干部先进事迹材料
2014/02/03 职场文书
篮球比赛策划方案
2014/06/05 职场文书
尊老爱亲美德少年事迹材料
2014/08/14 职场文书
Windows下redis下载、redis安装及使用教程
2021/06/02 Redis