【面试题】如何避免使用过多的 if else?

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

一、引言

相信大家听说过回调地狱——回调函数层层嵌套,极大降低代码可读性。其实,if-else层层嵌套,如下图所示,也会形成类似回调地狱的情况。

当业务比较复杂,判断条件比较多,项目进度比较赶时,特别容易使用过多if-else。其弊端挺多的,如代码可读性差、代码混乱、复杂度高、影响开发效率、维护成本高等。

因此,我们在日常编码时,有必要采取一些措施避免这些问题。本文的初衷不是建议大家完全不用if-else,而是希望我们能够在学会更多解决方案后更优雅地编码。


二、8种if-else的优化/替代方案

1. 使用排非策略:!、!!

逻辑非(logic NOT),是逻辑运算中的一种,就是指本来值的反值。

当你想这么写时……

1、判断是否为空
if(value === null || value === NaN || value === 0 || value === ''|| value === undefined   )
{
……
}

2、判断是否数组是否含有符合某条件的元素
const name = arr.find(item => item.status === 'error')?.name;
if(name !== undefined && name !== ''){
……
}
复制代码

不妨尝试这么写:

1、判断是否为空
if(!value){……}

2、判断是否数组是否含有符合某条件的元素
if(!!arr.find(item => item.status === 'error')?.name){……}
复制代码

2. 使用条件(三元)运算符: c ? t : f

三元运算符: condition ? exprIfTrue : exprIfFalse; 如果条件为真值,则执行冒号(:)前的表达式;若条件为假值,则执行最后的表达式。

当你想这么写时……

let beverage = '';
if(age > 20){
beverage = 'beer';
} else {
beverage = 'juice';
}
复制代码

不妨尝试这么写:

const beverage = age > 20 ? 'beer' : 'juice';
复制代码

tips: 建议只用一层三元运算符,多层嵌套可读性差。


3. 使用短路运算符:&&、 ||

  • && 为取假运算,从左到右依次判断,如果遇到一个假值,就返回假值,以后不再执行,否则返回最后一个真值;

  • || 为取真运算,从左到右依次判断,如果遇到一个真值,就返回真值,以后不再执行,否则返回最后一个假值。

当你想这么写时……

if (isOnline){
    makeReservation(user);
    }
复制代码

不妨尝试这么写:

 isOnline && makeReservation(user);
复制代码

4. 使用 switch 语句

当你想这么写时……

let result;
    if (type === 'add'){
    result = a + b;
    } elseif(type === 'subtract'){
    result = a - b;
    } elseif(type === 'multiply'){
    result = a * b;
    } elseif(type === 'divide'){
    result = a / b;
    } else {
    console.log('Calculation is not recognized');
    }
复制代码

不妨尝试这么写:

let result;
switch (type) {
   case'add':
     result = a + b;
     break;
   case'subtract':
     result = a - b;
     break;
   case'multiply':
     result = a * b;
     break;
   case'divide':
     result = a / b;
     break;
   default:
    console.log('Calculation is not recognized');
}
复制代码

个人认为,对于这类比较简单的判断,用switch语句虽然不会减少代码量,但是会更清晰喔。


5. 定义相关函数拆分逻辑,简化代码

当你想这么写时……

functionitemDropped(item, location) {
    if (!item) {
        returnfalse;
    } elseif (outOfBounds(location) {
        var error = outOfBounds;
        server.notify(item, error);
        items.resetAll();
        returnfalse;
    } else {
        animateCanvas();
        server.notify(item, location);
        returntrue;
    }
}
复制代码

不妨尝试这么写:

// 定义dropOut和dropIn, 拆分逻辑并提高代码可读性functionitemDropped(item, location) {
  const dropOut = function () {
    server.notify(item, outOfBounds);
    items.resetAll();
    returnfalse;
  };

  const dropIn = function () {
    animateCanvas();
    server.notify(item, location);
    returntrue;
  };

  return !!item && (outOfBounds(location) ? dropOut() : dropIn());
}
复制代码

细心的朋友会发现,在这个例子中,同时使用了前文提及的优化方案。这说明我们在编码时可以根据实际情况混合使用多种解决方案。


6. 将函数定义为对象,通过穷举查找对应的处理方法

  • 定义普通对象

对于方案3的例子,不妨尝试这么写:

functioncalculate(action, num1, num2) {
  const actions = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b,
    multiply: (a, b) => a * b,
    divide: (a, b) => a / b,
  };
​
  return actions[action]?.(num1, num2) ?? "Calculation is not recognized";
}
复制代码
  • 定义 Map 对象

普通对象的键需要是字符串,而 Map 对象的键可以是一个对象、数组或者更多类型,更加灵活。

let statusMap = newMap([
  [
    { role: "打工人", status: "1" },
    () => { /*一些操作*/},
  ],
  [
    { role: "打工人", status: "2" },
    () => { /*一些操作*/},
  ],
  [
    { role: "老板娘", status: "1" },
    () => { /*一些操作*/},
  ],
]);

let getStatus = function (role, status) {
  statusMap.forEach((value, key) => {
    if (JSON.stringify(key) === JSON.stringify({ role, status })) {
      value();
    }
  });
};

getStatus("打工人", "1"); // 一些操作复制代码

tips: JSON.stringify()可用于深比较/深拷贝。


7. 使用责任链模式

责任链模式:将整个处理的逻辑改写成一条责任传递链,请求在这条链上传递,直到有一个对象处理这个请求。

例如 JS 中的事件冒泡

简单来说,事件冒泡就是在一个对象上绑定事件,如果定义了事件的处理程序,就会调用处理程序。相反没有定义的话,这个事件会向对象的父级传播,直到事件被执行,最后到达最外层,document对象上。

这意味着,在这种模式下,总会有程序处理该事件。

再举个🌰,当你想这么写时……

functiondemo (a, b, c) {
  if (f(a, b, c)) {
    if (g(a, b, c)) {
      // ...
    }
    // ...elseif (h(a, b, c)) {
      // ...
    }
    // ...
  } elseif (j(a, b, c)) {
    // ...
  } elseif (k(a, b, c)) {
    // ...
  }
}
复制代码

不妨参考这种写法:

const rules = [
  {
    match: function (a, b, c) { /* ... */ },
    action: function (a, b, c) { /* ... */ }
  },
  {
    match: function (a, b, c) { /* ... */ },
    action: function (a, b, c) { /* ... */ }
  },
  {
    match: function (a, b, c) { /* ... */ },
    action: function (a, b, c) { /* ... */ }
  }
  // ...
]

// 每个职责一旦匹配,原函数就会直接返回。functiondemo (a, b, c) {
  for (let i = 0; i < rules.length; i++) {
    if (rules[i].match(a, b, c)) {
      return rules[i].action(a, b, c)
    }
  }
}
复制代码
引申话题——如何降低if else代码的复杂度?
相关文章阅读: 如何无痛降低 if else 面条代码复杂度 建议多读几次!!!

三、小结

本文粗略介绍了8种优化/替代if-else的方法,希望能给你日常编码带来一些启示😄。

正如开头所说,我们的目的不是消灭代码中的if-else,而是让我们在学会更多解决方案的基础上,根据实际情况选择更优的编码方式。因此,当你发现自己的代码里面存在特别多的if-else或当你想用if-else时,不妨停下来思考一下——如何能写得更优雅、更方便日后维护呢

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/97.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iOS-砸壳篇(两种砸壳方式)

CrackerXI砸壳呢&#xff0c;当时你要是使用 frida-ios-dump 也是可以的&#xff1b; https://github.com/AloneMonkey/frida-ios-dump frida-ios-dump: 代码中需要更改的&#xff1a;手机中的内网ip 密码 等 最后放到我的砸壳路径里&#xff1a; python dump.py -l查看应用…

【答疑现场】我一个搞嵌入式的,有必要学习Python吗?

【答疑现场】我一个搞嵌入式的&#xff0c;有必要学习Python吗&#xff1f; 文章目录1 写在前面2 一个结论3 Python在嵌入式领域能干啥事4 Python是用来干大事的5 友情推荐6 福利活动大家好&#xff0c;我是架构师李肯&#xff0c;一个专注于嵌入式物联网系统架构设计的攻城狮。…

【蓝桥杯嵌入式】ADC模数转换的原理图解析与代码实现(以第十一届省赛为例)——STM32G4

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都在这儿哦&#xff0c;欢迎大家前往订阅本专题&#xff0c;获取更多详细信息哦&#x1f38f;&#x1f38f;&#x1f38f; &#x1fa94;本系列专栏 - 蓝…

Linux--多线程(1)

目录 一、概念 二、理解 三、创建、退出、合并进程 //man pthread_create //Compile and link with -pthread. //1.为什么没有fun函数&#xff1f; //2.加上sleep来改进 //3.线程结束会不会影响主线程运行&#xff1f; //4.那如果主线程比较少呢&#xff1f; 四、如何…

IP协议+以太网协议

在计算机网络体系结构的五层协议中&#xff0c;第三层就是负责建立网络连接&#xff0c;同时为上层提供服务的一层&#xff0c;网络层协议主要负责两件事&#xff1a;即地址管理和路由选择&#xff0c;下面就网络层的重点协议做简单介绍~~ IP协议 网际协议IP是TCP/IP体系中两…

RecyclerView流程学习

RecyclerView流程学习模块划分绘制流程onMeasuremLayout为nullmLayout开启自动测量未开启自动测量onLayoutonDrawonLayoutChildren缓存预加载滚动和fling模块划分 RecyclerView中根据其功能可以分为以下几个模块&#xff1a; Recycler mRecycler // 缓存管理者&#xff0c;fi…

yolov5的基本配置

yolov5的基本配置train.pydata.yaml数据集标签文件格式:总结train.py def parse_opt(knownFalse):parser argparse.ArgumentParser()parser.add_argument(--weights, typestr, defaultROOT / yolov5s.pt, helpinitial weights path)parser.add_argument(--cfg, typestr, defau…

uniCloud在线升级APP配置教程

app在线升级背景实现思路流程流程背景 因用户需要添加手机h5页面来进数据操作实现思路流程 实现流程图流程 相关文档&#xff1a;帮助文档 https://uniapp.dcloud.net.cn/uniCloud/cf-functions.html 注册服务空间 https://unicloud.dcloud.net.cn/pages/login/login uni升级…

基于Yolv5s的口罩检测

1.Yolov5算法原理和网络结构 YOLOv5按照网络深度和网络宽度的大小&#xff0c;可以分为YO-LOv5s、YOLOv5m、YOLOv5l、YOLOv5x。本文使用YOLOv5s&#xff0c;它的网络结构最为小巧&#xff0c;同时图像推理速度最快达0.007s。YO-LOv5的网络结构主要由四部分组成&#xff0c;分别…

三天吃透MySQL八股文(2023最新整理)

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

博客系统(界面设计)

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录实现博客列表页预期效果导航栏页面主体左右布局左侧区域右侧区域完整代码实现博客详情页预期效果导航栏 左侧右侧完整代码实现…

全国程序员薪酬大曝光!看完我酸了····

2023年&#xff0c;随着互联网产业的蓬勃发展&#xff0c;程序员作为一个自带“高薪多金”标签的热门群体&#xff0c;被越来越多的人所关注。在过去充满未知的一年中&#xff0c;他们的职场现状发生了一定的改变。那么&#xff0c;程序员岗位的整体薪资水平、婚恋现状、职业方…

认识TomcatMavenServlet第一个Servlet程序

文章目录一、什么是Tomcat、什么是Servlet二、Tomcat的下载与使用关于下载启动欢迎页面查看可能出现的问题博客系统静态页面的部署三、什么是Maven四、第一个servlet程序1.创建Maven项目2.引入依赖3.创建目录结构4.编写程序5.打包程序6.部署程序7.验证小结五、servlet程序简化版…

学习 Python 之 Pygame 开发魂斗罗(四)

学习 Python 之 Pygame 开发魂斗罗&#xff08;四&#xff09;继续编写魂斗罗1. 创建子弹类2. 根据玩家方向和状态设置子弹发射的位置(1). 站立向右发射子弹(2). 站立向左发射子弹(3). 站立朝上发射子弹(4). 蹲下发射子弹(5). 向斜方发射子弹(6). 奔跑时发射子弹(7). 跳跃时发射…

图片的美白与美化

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…

Python雪花代码

前言 用python画个雪花玩玩&#xff0c;源码在文末公众号哈。 雪花类 class Snow(): #雪花类 def __init__(self): self.r 6 #雪花的半径 self.x ra.randint(-1000,1000) #雪花的横坐标 self.y ra.randint(-500,5…

读书笔记——《富爸爸穷爸爸》

《富爸爸穷爸爸》&#xff0c;以前不屑读这种书。这种书就是那种走进书店放在门口展销位的成功学著作&#xff0c;一眼看上去没什么实在的内容&#xff0c;看上去很不靠谱&#xff0c;感觉就是骗一些社会底层又做着暴富梦的人来买的&#xff0c;但是由于自身原因或环境局限根本…

MySQL基本查询

文章目录表的增删查改Create&#xff08;创建&#xff09;单行数据 全列插入多行数据 指定列插入插入否则更新替换Retrieve&#xff08;读取&#xff09;SELECT列全列查询指定列查询查询字段为表达式查询结果指定别名结果去重WHERE 条件基本比较BETWEEN AND 条件连接OR 条件连…

【面试题】Python软件工程师能力评估试题(一)

文章目录前言应试者需知&#xff08;一&#xff09;Python 语言基础能力评估1、理解问题并完成代码&#xff1a;2、阅读理解代码&#xff0c;并在空白处补充完整代码&#xff1a;3、编写一个装饰器&#xff1a;exposer4、阅读代码并在空白处补充完整代码&#xff1a;5、自行用P…

嵌入式 串口通信

目录 1、通信的基本概念 1.1 串行通信 1.2 并行通信 2、串行通信的特点 2.1 单工 2.2 半双工 2.3 全双工 3、串口在STM32的引脚 4、STM32的串口的接线 4.1 STM32的串口1和电脑通信的接线方式 4.2 单片机和具备串口的设备连接图 5、串口通信协议 6、串口通信…