在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 相关文章推荐
解决 FireFox 下[使用event很麻烦] 的问题.
Aug 22 Javascript
对象的类型:本地对象(1)
Dec 29 Javascript
Open and Print a Word Document
Jun 15 Javascript
BootStrap网页中代码显示用法详解
Oct 21 Javascript
微信小程序 九宫格实例代码
Jan 21 Javascript
详解浏览器渲染页面过程
Feb 09 Javascript
js 去掉字符串前后空格实现代码集合
Mar 25 Javascript
浅谈关于axios和session的一些事
Jul 13 Javascript
详解React 16 中的异常处理
Jul 28 Javascript
Vue插值、表达式、分隔符、指令知识小结
Oct 12 Javascript
js实现经典贪吃蛇小游戏
Mar 19 Javascript
微信小程序自定义modal弹窗组件的方法详解
Dec 20 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多图上传小程序代码
2011/07/17 PHP
destoon数据库表说明汇总
2014/07/15 PHP
PHP图像识别技术原理与实现
2016/10/27 PHP
在 Laravel 中 “规范” 的开发短信验证码发送功能
2017/10/26 PHP
PHP利用DWZ.CN服务生成短网址
2019/08/11 PHP
jQuery Ajax 全解析
2009/02/08 Javascript
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
javascript mouseover、mouseout停止事件冒泡的解决方案
2009/04/07 Javascript
一些技巧性实用js代码小结
2009/10/14 Javascript
精选的10款用于构建良好易用性网站的jQuery插件
2011/01/23 Javascript
jQuery获取注册信息并提示实现代码
2013/04/21 Javascript
jquery实现pager控件示例
2014/04/09 Javascript
javacript使用break内层跳出外层循环分析
2015/01/12 Javascript
javascript事件绑定学习要点
2016/03/09 Javascript
详解webpack3编译兼容IE8的正确姿势
2017/12/21 Javascript
vue 实现剪裁图片并上传服务器功能
2018/03/01 Javascript
vue2.0 实现导航守卫(路由守卫)
2018/05/21 Javascript
vue3.0 CLI - 2.3 - 组件 home.vue 中学习指令和绑定
2018/09/14 Javascript
element-ui upload组件多文件上传的示例代码
2018/10/17 Javascript
javascript触发模拟鼠标点击事件
2019/06/26 Javascript
js刷新页面location.reload()用法详解
2019/12/09 Javascript
nodejs nedb 封装库与使用方法示例
2020/02/06 NodeJs
jQuery实现鼠标拖动图片功能
2021/03/04 jQuery
[04:00]黄浦江畔,再会英雄——完美世界DOTA2 TI9应援视频
2019/07/31 DOTA
推荐下python/ironpython:从入门到精通
2007/10/02 Python
tensorflow 输出权重到csv或txt的实例
2018/06/14 Python
自定义django admin model表单提交的例子
2019/08/23 Python
python GUI库图形界面开发之PyQt5单行文本框控件QLineEdit详细使用方法与实例
2020/02/27 Python
HTML5 body设置自适应全屏
2020/05/07 HTML / CSS
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
关于礼仪的演讲稿
2014/01/04 职场文书
高中化学教学反思
2014/01/13 职场文书
绿化工程实施方案
2014/03/17 职场文书
pytorch实现手写数字图片识别
2021/05/20 Python
利用Python判断整数是否是回文数的3种方法总结
2021/07/07 Python
MongoDB修改oplog大小的四种方法
2022/04/11 MongoDB