JavaScript条件嵌套代码的可读性优化

459 阅读2分钟

数据结构

功能是实现历史记录的数据添加,数据按年月日组织如下:

"timeData": {
  "2019": {  //年
    "11": {  //月
      "12": [   //日
        {
          "start": "21:14",
          "end": "21:25",
          "duration": "0:11"
        },
        {
          "start": "23:34",
          "end": "23:45",
          "duration": "0:11"
        }
      ],
      "13": [
        {
          "start": "23:34",
          "end": "23:45",
          "duration": "0:11"
        }
      ]
    }
  }
}

if else实现

添加时需要考虑没有对应年月日的情况,初次通过if else嵌套实现如下:

原理是依次尝试按指定日、月、年去获取数据,有数据则说明该日期以存在,该日没有则查月,月没有则查年,年没有则添加该年月日,有年无月则添加该月日,有月无日则添加该日。

  let dbData = getData(start.slice(0, 10)) //取指定年月日数据
  if (dbData) {
    dbData.push(data)
    save()
  } else {
    dbData = getData(start.slice(0, 7)) //取指定年月数据
    log('dbData', dbData)
    if (dbData) {
      dbData[sD] = [data]
      save()
    } else {
      dbData = getData(start.slice(0, 4)) //取指定年数据
      log('dbData', dbData)
      if (dbData) {
        dbData[sM] = { [sD]: [data] }
        save()
      } else {
        dbData = getData(start.slice(0, 0)) //取数据对象
        log('dbData', dbData)
        if (dbData) {
          dbData[sY] = { [sM]: { [sD]: [data] } }
          save()
        } else {
          log('Error: addTime startdata error')
        }
      }
    }
  }

可以看到if else嵌套方式可读性较差,各级相似很难一眼看懂逻辑。

switch实现

下面通过dbData的“或”赋值和gData函数,减少冗余代码并巧妙的定位数据情况(location),并结合switch语句根据数据情况进行处理:

  let location: number = 0  
  let [ymd, ym, y] = [10, 7, 4] //ymd代表年月日的字符数,如: 2019-04-20 为10
  let dbData = gData(ymd) || gData(ym) || gData(y) || gData(0) //依次按日,月,年查找数据, 有则赋值
  function gData(i: number) {
    location = i //用于定位数据提取的级别
    return getData(start.slice(0, i))
  }

  //根据数据的级别添加数据, 比如有年无月,则添加月日数据
  switch (location) {
    case ymd:
      dbData.push(data)
      save()
      break
    case ym:
      dbData[sD] = [data]
      save()
      break
    case y:
      dbData[sM] = { [sD]: [data] }
      save()
      break
    case 0:
      dbData[sY] = { [sM]: { [sD]: [data] } }
      save()
      break
    default:
      log('Error: addTime startdata error')
      break
  }

对象字面量实现

过了一天看到switch语句可用对象字面量替代,能大大降低圈复杂度,便将已上代码简化如下:

  let location: number = 0
  let [ymd, ym, y] = [10, 7, 4] //ymd代表年月日的字符数,如: 2019-04-20 为10
  let dbData = gData(ymd) || gData(ym) || gData(y) || gData(0) //依次按日,月,年查找数据, 有则赋值
  function gData(i: number) {
    location = i //用于定位数据提取的级别
    return getData(start.slice(0, i)) //通过日期查找对应的年月日数据
  }

  //根据已有的日期的情况添加数据, 比如有年无月,则添加月日数据
  let situation = {
    [ymd]: () => dbData.push(data),
    [ym]: () => (dbData[sD] = [data]),
    [y]: () => (dbData[sM] = { [sD]: [data] }),
    0: () => (dbData[sY] = { [sM]: { [sD]: [data] } }),
  }
  situation[location]()
  save()

原文发布自:有度博客