使用一个数据对象较深层次的属性,为了容错需要逐层判断是否存在某个属性,这种长长的判断应该如何写比较优雅?

使用一个数据对象较深层次的属性,为了容错需要逐层判断是否存在某个属性,这种长长的判断应该如何写比较优雅?

比如:
`
if (data.school && data.school.class && data.school.class.students && data.school.class.students[10] && data.school.class.students[10].name) {

alert(data.school.class.students[10].name)

}
`

阅读 4.3k
5 个回答

Optional chaining

babel和TS都支持了

或者写个自带maybe monad的proxy

序列化对象(空则忽略)->正则匹配,应该是满足你的问题域的,不过序列化还会层级遍历对象,所以在时间复杂度上没有优化
另:见过同事用Optional封装域对象并使用 JOOQ,那个全是链式调用,不过比你不停手写判断要方便

方案一:
这样写美化一些,比都写在一行要好看:

if (data.school
  && data.school.class
  && data.school.class.students
  && data.school.class.students[10]
  && data.school.class.students[10].name) {
  alert(data.school.class.students[10].name)
}

方案二:
写个方法找对象的子属性:

Object.prototype.getObjVal = function(key) {
  const _ = (obj) => {
    const keys = Object.keys(obj)
    const len = keys.length
    for (let i = 0; i < len; i++) {
      const k = keys[i]
      const val = obj[k]
      if (key === k) {
        return val
      } else if (Object.prototype.toString.call(val) === '[object Object]') {
        let res = _(val)
        if (res !== undefined) {
          return res
        }
      }
    }
  }
  return _(this)
}
// 下面就是简化后的代码:
const students = data.getObjVal('students')
if (students && students[10]) {
  students[10].name && alert(students[10].name)
}
  

封装一个方法,强制改变数据,保证需要的数据一直存在

// 定义一个数据格式,保证 res.data.staff.list 不会出错,且为数组
const MY_DATA_FORMAT = {
  code: '',
  data: {
    staff: {
      list: []
    }
  }
}

const data1 = ns.dataLayout(MY_DATA_FORMAT, {
  data: {
    staff: {
      id: '123',
      name: '加快建'
    }
  }
})

const data2 = ns.dataLayout(MY_DATA_FORMAT, '没有数据')

console.log('data1', data1)
console.log('data2', data2)

图片描述

用 try catch ?

var data = {}

console.log('之前代码');

try {
    alert(data.school.class.students[10].name)
} catch (error) {

}

console.log('之后代码');
推荐问题