如何优雅地Coding,减少if else语句

498 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情

出来工作几年,相信大家都会看到过几次经手的屎山项目,里面夹杂着非常多的业务逻辑代码。

表面上说是可以锻炼思维,提升业务能力,其实就是对着一堆if else语句来擦屁股,有时候debugger排查分分钟让我们怀疑人生,不,我不能做只会使用if else 做CURD操作的工具人,我们要使用一些高级语法来优雅地写代码。

那么都有哪些coding方式可以完美取代if else?

二元运算符

在函数定义中,有没有更加优雅的coding手法?有,我们可以使用||运算符来实现,如下:

function fn(a){
  if(!a){
    a = 'test'
  }
}

// 使用 || 运算符来实现
function fn(name){
  name = name || 'test'
}

三元运算符

没错,我第一个想到的就是三元运算符,也是我日常工作中最常使用的减少代码量的方法。

在这里我只推荐一层三元表达式,因为多层嵌套的三元表达式运算符不具备很良好的可读性(格式化会发现跟回调地狱差不多)

const fn = (isTure) => {
  if (isTure) {
    return 1
  } else {
    return 0
  }
}
  //   使用三元运算符
  const fn = (isTrue) => {
    return isTrue ? 1 : 0
  }

三元运算符的使用场景还很多,比如:条件赋值,递归...

// num值在nBoolean为true时为0,否则为5
let num = nBoolean ? 10 : 5


//   求0-n之间整数的和
let sum = 0
function add(n) {
  sum += n
  return n >= 2 ? add(n - 1) : sum
}
let numb = add(10) //55

这么一对比,是不是代码要简洁很多有木有!?

switch case

三元运算符虽然能够让代码更加简洁,但是缺点是只能处理简单的判断,超过3个以上的判断,个人是不推荐再使用三元运算符,因为看着脑壳痛,写着也累,看着也累。

这时候我就推荐使用switch case!

switch case的优点是可读性比较高,对于多重判断,可以使用switch case

举个栗子:

有A,B,C,D四种类型,在A,B输出1,C输出2,D输出3,默认输出0。

let type = 'A'
//   if else if
if (type === 'A' || type === 'B') {
  console.log(1)
} else if (type === 'C') {
  console.log(2)
} else if (type === 'D') {
  console.log(3)
} else {
  console.log(0)
}

目前看起来还行,但是一旦业务量一多,那也是妥妥的回调地狱!

//   switch case
switch (type) {
  case 'A':
  case 'B':
    console.log(1)
    break
  case 'C':
    console.log(2)
    break
  case 'D':
    console.log(3)
    break
  default:
    console.log(0)
}

对象配置

如果条件超过三种,else if 写起来不太优雅,switch case代码行数也差不多,就像下面的代码

function formatData(a) {
  let c = ''
  if (a === 1) {
    c = '汉族'
  } else if (a === 2) {
    c = '苗族'
  } else if (a === 3) {
    c = '维吾尔族'
  } else if (a === 4) {
    c = '回族'
  } else if (a === 5) {
    c = '藏族'
  }
  // ... 等等等等


  return c
}
const result = formatData(2) // 对应的苗族

这个要是有64个名族,那我们要写64个else if 啊 ~~,着实有点可怕,那么有没有好的方法呢,看下面代码:

const obj = {
  1: "汉族",
  2: "苗族",
  3: "维吾尔族",
  4: "回族",
  5: "藏族",
  // ...等等等等
};
function formatData(a) {
  return obj[a]
}
const result = formatData(2);  // 苗族

上面的代码直接省去64个 else if, 有点小兴奋。

有时候我在实际开发遇到过这样一个情景,我需要根据用户不同的操作类型对同一份数据进行不同加工,比如新增,修改,删除等。那么我用 else if 是这么做的:

function del() {} // 删除操作
function add() {} // 新增
function update() {} // 更新
function process(operateType) {
  if (operateType === 'del') {
    del()
  } else if (operateType === 'add') {
    add()
  } else if (operateType === 'update') {
    update()
  }
}
process('del') // 删除

当然我们也可以使用 ES6map 数据结构,像这样:

let typeFn = new Map([
  ['del_1', function () {/*do something*/ }],
  ['add_2', function () {/*do something*/ }],
  ['update_3', function () {/*do something*/ }],
]);

function process(operateType, status) {
  typeFn.get(`${operateType}_${status}`)();
};
process('del', 1); // 删除

数组配置

在处理条件判断时,我们常会遇到条件与对应结果全部已知的情况,比如我们要根据用户的经验设置等级头衔,[0,100)–萌新,[100,200)–骑士,[200,300)–英雄,[300-无限大]–黄金圣斗士,那么用else if怎么写已经没有悬念了:

function getHero(experience) {
  if (experience < 100) {
    return '萌新'
  } else if (experience < 200 && experience >= 100) {
    return '骑士'
  } else if (experience < 300 && experience >= 200) {
    return '英雄'
  } else if (experience >= 300) {
    return '黄金圣斗士'
  }
}
const level = getHero(351) //黄金圣斗士

对于这种条件与结果已知的情况,我们其实可以通过数组配置的形式将条件结果抽离出来,像这样:

function getHero(param) {
  let experience = [300, 200, 100]
  let level = ['黄金圣斗士', '英雄', '骑士', '萌新']


  for (let i = 0; i < experience.length; i++) {
    if (param >= experience[i]) {
      return level[i]
    }
  }
  return level[level.length - 1]
}


const level = getHero(250) //英雄

这么做的好处就是便于管理条件与执行结果,如果后面新增了等级判断,我们不用去修改业务逻辑中的 else if 语句长度,只用单纯维护我们抽离的数据即可。

还有一个大杀器:

对象配置/策略模式

策略模式就是将一系列算法封装起来,并使它们相互之间可以替换。被封装起来的算法具有独立性,外部不可改变其特性。

接下来我们用对象配置的方法实现一下上述的例子:

let type = 'A'

let data = {
  'A': 1,
  'B': 1,
  'C': 2,
  'D': 3,
  default: 0
}
console.log(data[type]) // 1

根据不同的用户使用不同的折扣,如:普通用户不打折,普通会员用户9折,年费会员8.5折,超级会员8折。

使用对象配置/策略模式实现:

// 获取折扣 -- 使用对象配置/策略模式
const getDiscount = (userKey) => {
  // 我们可以根据用户类型来生成我们的折扣对象
  let discounts = {
    '普通会员': 0.9,
    '年费会员': 0.85,
    '超级会员': 0.8,
    'default': 1
  }
  return discounts[userKey] || discounts['default']
}
console.log(getDiscount('普通会员')) // 0.9

看着如此简洁的代码,是不是内心有一股幸福感油然而生!

总结

以上,我们大致介绍了6种可取代 if else 的方式,具体还是要看业务需求哦 ~