在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 KeyDown、KeyPress和KeyUp事件的区别与联系
Dec 03 Javascript
JavaScript实现数组随机排序的方法
Jun 26 Javascript
基于jQuery实现左右图片轮播(原理通用)
Dec 24 Javascript
浅析js的模块化编写 require.js
Dec 07 Javascript
详解Vue自定义过滤器的实现
Jan 10 Javascript
js 性能优化之算法和流程控制
Feb 15 Javascript
详解angularJS自定义指令间的相互交互
Jul 05 Javascript
一个基于react的图片裁剪组件示例
Apr 18 Javascript
JS关于刷新页面的相关总结
May 09 Javascript
浅谈node.js 命令行工具(cli)
May 10 Javascript
Vue获取微博授权URL代码实例
Nov 04 Javascript
微信小程序绘制半圆(弧形)进度条
Nov 18 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 模拟POST|GET操作实现代码
2010/07/20 PHP
php计算整个目录大小的方法
2015/06/19 PHP
PHP简单实现模拟登陆功能示例
2017/09/15 PHP
Thinkphp5.0 框架使用模型Model添加、更新、删除数据操作详解
2019/10/11 PHP
js用图作提交按钮或超连接
2008/03/26 Javascript
JavaScript对象模型-执行模型
2008/04/28 Javascript
js中function()使用方法
2013/12/24 Javascript
JS+CSS模拟可以无刷新显示内容的留言板实例
2015/03/03 Javascript
JS继承之借用构造函数继承和组合继承
2016/09/07 Javascript
使用AngularJS编写多选按钮选中时触发指定方法的指令代码详解
2017/07/24 Javascript
js分页之前端代码实现和请求处理
2017/08/04 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
2017/09/28 Javascript
JS处理一些简单计算题
2018/02/24 Javascript
深入理解NodeJS 多进程和集群
2018/10/17 NodeJs
详解Vue前端生产环境发布配置实战篇
2019/05/07 Javascript
nodejs对项目下所有空文件夹创建gitkeep的方法
2019/08/02 NodeJs
layui.use模块外部使用其内部定义的js封装函数方法
2019/09/16 Javascript
vue实现整屏滚动切换
2020/06/29 Javascript
[03:38]TI4西雅图DOTA2前线报道 71专访
2014/07/08 DOTA
Python常见数据结构详解
2014/07/24 Python
利用Python获取操作系统信息实例
2016/09/02 Python
python实现转圈打印矩阵
2019/03/02 Python
python聚类算法解决方案(rest接口/mpp数据库/json数据/下载图片及数据)
2019/08/28 Python
深入浅析Python 中的sklearn模型选择
2019/10/12 Python
Python调用.net动态库实现过程解析
2020/06/05 Python
python else语句在循环中的运用详解
2020/07/06 Python
利用Python批量识别电子账单数据的方法
2021/02/08 Python
亚瑟士美国官网:ASICS美国
2017/02/01 全球购物
日本小田急百货官网:Odakyu
2018/07/19 全球购物
匡威荷兰官方网站:Converse荷兰
2018/10/24 全球购物
什么是静态路由?什么是动态路由?各自的特点是什么?
2015/09/16 面试题
银行工作检查书范文
2014/01/31 职场文书
考博专家推荐信
2014/05/10 职场文书
Python Django ORM连表正反操作技巧
2021/06/13 Python
python神经网络学习 使用Keras进行回归运算
2022/05/04 Python
Linux服务器离线安装 nginx的详细步骤
2022/06/16 Servers