注意以下一开始是当作没有可选链的

lodash.get 是做什么的

有时我们有这样的需求——需要获取某个结构中比较深层次的一个属性,比如这样:

  1. const obj = {
  2. a:{
  3. b:{
  4. c:{
  5. name:'zhou'
  6. }
  7. }
  8. }
  9. }

想要拿到里面的name,也就是说需要一层层的去查找。但有时还不能确定这条路径是否正确,这还需要避免发生TypeError错误。像这样:

  1. const obj = {
  2. a:{
  3. b:{
  4. c:{
  5. name:'zhou'
  6. }
  7. }
  8. }
  9. }
  10. a && a.b && a.b.c && a.b.c.name


lodash.get就是解决这个问题的,用这个方法就可以简化为这样:

  1. _.get(obj, 'a.b.c.name')

如何实现 lodash.get

首先看看文档

  1. _.get(object, path, [defaultValue])

根据 object对象的path路径获取值。 如果解析 valueundefined会以 defaultValue取代。

关于其参数:

  • 比较特殊的一点就是 path可以是Array|string
  • 以及传入的 object 可以是嵌套对象,也可以是嵌套的数组,也就是说 path中也可以是数组的路径

数组的路径表示是用 []的,所以要先将其全部转换为.运算符,之后再组成数组

  1. //a[0].b -> a.0.b -> ['a', '0', 'b']
  2. const tpath = path.replace(/\[(\d+)\]/g,'.$1').split('.')

然后就是一层层往下走就完事了:

  1. function get(object, path, defaultValue = undefined){
  2. const tpath = path.replace(/\[(\d+)\]/g,'.$1').split('.')
  3. let res = object
  4. for(const t of tpath){
  5. res = res[p]
  6. if(res === undefined) return defaultValue
  7. }
  8. return res
  9. }

上面的代码乍一看好像没有问题,实际上:res一开始是有可能为 undefined的,这样就会报出TypeError: Cannot read properties of undefined的错误。
我们可以这样改进一下那行代码

  1. function get(object, path, defaultValue = undefined){
  2. const tpath = path.replace(/\[(\d+)\]/g,'.$1').split('.')
  3. let res = object
  4. for(const t of tpath){
  5. res = Object(res)[p] //*
  6. if(res === undefined) return defaultValue
  7. }
  8. return res
  9. }

这样如果res为空,那么也会先变为一个空对象{}而已,访问不不存在的键也就是返回符合预期的 undefined


可选链

ES2020新增 可选链条 ?. 非常方便,像上面的需求可以直接:

  1. const obj = {
  2. a:{
  3. b:{
  4. c:{
  5. name:'zhou'
  6. }
  7. }
  8. }
  9. }
  10. obj?.a?.b?.c?.name