1

前端取后端数据的时候, 经常会遇到一些比较深层的结构。比如

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')

  1. 可选链操作符?. 目前主流的PC端浏览器均已支持

address?.province?.city?.district?.name

  1. 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
  1. 上面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'])
// => 邗江区
  1. 巧用数组的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) 
// => 邗江区

本文的方法参考来源

  1. 鱼头大佬的公众号: 鱼头的Web海洋的文章《你不知道的 Proxy:ES6 Proxy 可以做哪些有意思的事情?
  2. js对象如何优雅的取一个深度的值?文章中的评论

Ping
11 声望1 粉丝