前端取后端数据的时候, 经常会遇到一些比较深层的结构。比如
const address = {
province: {
name: '江苏省',
city: {
name: '扬州市'
district: {
name: '邗江区'
}
}
}
}
这时候如果我们要取最里面区域的名字时候, 最简单的写法就是:`let district = address.province.city.district.name`, 如果后台返回的是正常的数据的还好, 如果遇到其中有null或者结构不全的, 很容易就会报'xxx undefined'的js错误, 如果项目再是要求TS强类型检查的, 可能连编译都不能通过, 就很头疼。
为了避免这个问题, 我们可能硬着头皮这么写:
let district =address && address.province && address.province.city && address.province.city.district && address.province.city.district.name
但是这样写, 就显得很繁琐, 而且不美观。 于是我们可以通过以下几种办法
1. Lodash的get方法
_.get(address, 'province.city.district.name')
2. 可选链操作符?. 目前主流的PC端浏览器均已支持
address?.province?.city?.district?.name
3. Proxy代理监听
/**
* @param target
* @param exec 取值属性
* @returns {*}
*/
function getter(target, exec = '_') {
return new Proxy({}, {
get: (o, n) => {
return n === exec ?
target :
getter(typeof target === 'undefined' ? target : target[n], exec)
}
});
}
```
```
getter(address).province.city.district.name._ // 邗江区
getter(address).province.city.district.name1._ // undefined
4. 上面Proxy的ES5写法
function getter(obj, arr) {
return arr.length === 0 ? obj : getter(typeof obj === 'undefined' ? undefined : obj[arr[0]], arr.slice(1))
}
getter(address, ['province', 'city', 'district', 'name'])
// => 邗江区
5. 巧用数组的reduce方法
function getIn(p, o) {
return p.reduce(function(xs, x) {
return (xs && xs[x]) ? xs[x] : null;
}, o);
}
getIn(['province', 'city', 'district', 'name'], address)
// => 邗江区
6. 开源方法: 采用Github 上的一个名为 safe-touch 的库 , 链接: https://github.com/EnixCoda/safe-touch
本文的方法参考来源
1. 鱼头大佬的公众号: 鱼头的Web海洋的文章《你不知道的 Proxy:ES6 Proxy 可以做哪些有意思的事情?
2. [js对象如何优雅的取一个深度的值?](https://segmentfault.com/q/1010000016285893)文章中的评论