壹 ❀ 引

在JavaScript开发中,条件判断语句的使用频率是极高的,而对于条件判断简单易读的if else应该都是大家的首选。可是代码写的久了,我们总是希望自己的代码看着能更为简洁规范(逼格更高),那么今天我们就由浅到深介绍几种实用小技巧,帮大家减少代码中的if else。说在开头,本文并未有消灭或歧视 if else的意思,if else的好用都知道,这里只是在某些特定场景为大家额外提供一种思路罢了,如何使用还请自行抉择,那么本文开始。

 贰 ❀ 短路求值

在函数定义时,常有若函数调用未提供参数则使用默认值的情景,当然我们可以使用if else来解决这个问题:

  1. function fn(name) {
  2. if(!name){
  3. name = '听风是风';
  4. };
  5. console.log(name);
  6. };
  7. fn();//听风是风
  8. fn('行星飞行');//行星飞行

有没有更优雅的做法呢?当然,我们可以使用短路求值,像这样:

  1. function fn(name) {
  2. name = name || '听风是风';
  3. console.log(name);
  4. };
  5. fn();//听风是风
  6. fn('行星飞行');//行星飞行

我们简单复习下 ||或 和 &&与 的概念,||表示两者任意一个为真便为真,&&表示两者都为真才是真,任意一个为假就是假。

为什么这个特定能用在变量赋值呢?其实这是利用了 || 前者为真后者不判断,&&前者为假后者不判断的特点,来看个例子:

  1. function fn() {
  2. console.log(1);
  3. };
  4. true || fn(); //不执行
  5. false && fn(); //不执行
  6. false || fn(); //
  7. true && fn() //

所以上面的短路求值中,当name有值时后面的默认值就被忽略了不判断,而name无值时便会判断后者取到默认值。

短路求值除了用在变量赋值外,还能用于函数调用,比如在下方例子为假时才调用某个方法:

  1. let name = false;
  2. function fn() {
  3. console.log(1);
  4. };
  5. //if
  6. if (!name) {
  7. fn();//
  8. };
  9. //短路
  10. !name && fn();//

对于函数形参短路赋值其实有个缺点,假设我的参数就是0,false或者null,因为短路的特性会被认为假,这样我们无法拿到想要的值,更佳的做法是使用ES6的形参默认值,像这样:

  1. function fn(param) {
  2. param = param || 1;
  3. console.log(param);
  4. };
  5. fn(0); //
  6. fn(null); //
  7. fn(false); //
  8.  
  9. //使用形参默认值
  10. function fn1(param = 1) {
  11. console.log(param);
  12. };
  13. fn1(); //
  14. fn1(0); //
  15. fn1(null); //null
  16. fn1(false); //false

 叁 ❀ 三元运算符

三元运算符我想大家都不会陌生,在开发中三元运算的使用场景其实非常多,比如我希望为条件为 true时变量为1,反之为0,通过三元运算符我们可以这样做:

  1. let blo = true;
  2. let num;
  3. if (blo) {
  4. num = 1;
  5. } else {
  6. num = 0;
  7. };
  8. console.log(num);//
  9.  
  10. //三元运算符
  11. blo =false;
  12. blo ? num = 1 : num = 0;
  13. console.log(num);//

比如我们希望条件为true时调用函数fn,为false时什么也不做,使用三元看起来也会更加舒服:

  1. let blo = true;
  2. let fn = function () {
  3. console.log(1);
  4. };
  5. //if
  6. if (blo) {
  7. fn(); //
  8. };
  9.  
  10. //三元
  11. blo ? fn() : null;//

在开发中函数常常需要 return 一份数据回去,有时候根据条件不同我们可能要分别对应返回不同的数据,三元也能解决这个问题:

  1. let fn = function () {
  2. let flo = true;
  3. if (flo) {
  4. return 1;
  5. } else {
  6. return 2;
  7. };
  8. };
  9. let f = fn(); //
  10.  
  11. let fn1 = function () {
  12. let flo = true;
  13. //三元
  14. return flo ? 1 : 2;
  15. };
  16. let f1 = fn1();//

三元结合return的操作非常适合我们递归处理时做收尾工作,如果满足条件继续递归,不满足跳出递归,比如我们要求正整数N到0之间所有整数之和,可以这么写:

  1. let result = 0;
  2. function add(n){
  3. result += n
  4. return n>=2 ? add(n-1) : result;
  5. };
  6. let num = add(10);//

怎么样?看着是不是特别简洁舒服。需要注意的是,三元运算符的表达式只能是单语句,否则无法使用,比如下方例子中由于执行语句超过了2句,这就无法使用三元运算符改写了:

  1. let i = 5;
  2. if (i > 0) {
  3. //执行语句超过2句
  4. console.log(1);
  5. i = 0;
  6. };

 肆 ❀ switch case

短路求值与三元运算符固然好用,但其实有一个遗憾,它们都只能解决非A即B的条件判断,凡是条件判断超过两种就显得十分无力了。那难道我们只能使用 else if 吗,其实可以使用switch case。

例如A情况我们希望A情况输出a,B情况输出b,C情况输出c,其它情况输出d,用 else if 与switch case分别是这样:

  1. let name = 'B';
  2. //if else if
  3. if (name === 'A') {
  4. console.log('a');
  5. } else if (name === 'B') {
  6. console.log('b');
  7. } else if (name === 'C') {
  8. console.log('c');
  9. } else {
  10. console.log('d');
  11. };
  12.  
  13. //switch case
  14. switch (name) {
  15. case 'A':
  16. console.log('a');
  17. break;
  18. case 'B':
  19. console.log('b');
  20. break;
  21. case 'C':
  22. console.log('c');
  23. default:
  24. console.log('d');
  25. };

那么我们希望A或B情况输出1,C情况输出2,其它情况输出3呢,switch case其实也能做到:

  1. let name = 'B';
  2. //if else if
  3. if (name === 'A' || name === 'B') {
  4. console.log(1);
  5. } else if (name === 'C') {
  6. console.log(2);
  7. } else {
  8. console.log(3);
  9. };
  10.  
  11. //switch case
  12. switch (name) {
  13. case 'A':
  14. case 'B':
  15. console.log(1);
  16. break;
  17. case 'C':
  18. console.log(2);
  19. default:
  20. console.log(3);
  21. };

当然我想大多数人还是会觉得switch case写起来贼麻烦,尽管它的可读性确实比 else if 更高,没关系,就算作为了解也没有坏处。

 伍 ❀ 对象配置

条件超过三种,else if 写起来不太优雅,switch case又觉得麻烦,有没有更棒的做法呢?我在实际开发遇到过这样一个情景,我需要根据用户不同的操作类型对同一份数据进行不同加工,比如新增,修改,删除等。那么我用else if是这么做的:

  1. function del() {
  2. //删除操作
  3. };
  4.  
  5. function add() {
  6. //新增
  7. };
  8.  
  9. function update() {
  10. //更新
  11. };
  12.  
  13. function process(operateType) {
  14. if (operateType === 'del') {
  15. del()
  16. } else if (operateType === 'add') {
  17. add()
  18. } else if (operateType === 'update') {
  19. update()
  20. };
  21. };
  22. process('del');//删除

一种很棒的做法就是通过对象配置,将你的操作类型作为key,具体操作的函数作为value,像这样:

  1. function del() {
  2. //删除操作
  3. };
  4.  
  5. function add() {
  6. //新增
  7. };
  8.  
  9. function update() {
  10. //更新
  11. };
  12. let typeFn = {
  13. 'del': del,
  14. 'add': add,
  15. 'update': update
  16. };
  17.  
  18. function process(operateType) {
  19. typeFn[operateType]();
  20. };
  21. process('del'); //删除

怎么样,有没有眼前一亮呢?我们将需求升级,现在除了判断操作type类型外,还得额外附加一个状态类型,else if是这样,这里简单描述下:

  1. function process(operateType, status) {
  2. if (operateType === 'del' && status === 1) {
  3. del()
  4. } else if (operateType === 'add'&& status === 2) {
  5. add()
  6. } else if (operateType === 'update'&& status === 3) {
  7. update()
  8. };
  9. };

不太优雅,通过对象配置做法,我们其实只用将参数简单配置就OK了,像这样是不是更清爽呢:

  1. let typeFn = {
  2. 'del_1': del,
  3. 'add_2': add,
  4. 'update_3': update
  5. };
  6.  
  7. function process(operateType,status) {
  8. typeFn[`${operateType}_${status}`]();
  9. };
  10. process('del',1); //删除

什么,对象配置的调用方式语义化不太明显?那各位可曾对ES6的map数据结构有了解呢,如果你觉得这样的调用不太实在,我们再改改,将调用条件与函数配置成map数据,像这样:

  1. let typeFn = new Map([
  2. ['del_1', function () {/*do something*/ }],
  3. ['add_2', function () {/*do something*/ }],
  4. ['update_3', function () {/*do something*/ }],
  5. ]);
  6.  
  7. function process(operateType, status) {
  8. typeFn.get(`${operateType}_${status}`)();
  9. };
  10. process('del', 1); //删除

我们通过map数据的get方法去数据中找到方法执行,这下可读性总强一点了吧,诸君可否满意呢?

 陆 ❀ 数组配置

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

  1. function youAreMyHero(experience) {
  2. if (experience < 100) {
  3. return '萌新';
  4. } else if (experience < 200 && experience >= 100) {
  5. return '骑士';
  6. } else if (experience < 300 && experience >= 200) {
  7. return '英雄';
  8. } else if (experience >= 300) {
  9. return '传说';
  10. };
  11. };
  12. let level = youAreMyHero(351); //传说

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

  1. function youAreMyHero(param) {
  2. let experience = [300, 200, 100];
  3. let level = ['传说', '英雄', '骑士', '萌新'];
  4.  
  5. for (let i = 0; i < experience.length; i++) {
  6. if (param >= experience[i]) {
  7. return level[i];
  8. };
  9. };
  10. return level[level.length - 1];
  11. };
  12.  
  13. let level = youAreMyHero(250); //英雄

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

 柒 ❀ 总

那么到这里,我们大致介绍了五种可取代if else的方式,我们知道短路运算符除了短路求值,还能用于函数调用;三元运算符也不仅仅是处理变量赋值,在return场景结合三元用起来居然如此舒适。

在文章后半段,我们还了解了对象配置,利用map数据结构,以及数据实行来解决特殊场景。我并不推荐为了追求高逼格而牺牲代码可读性,但我更希望在你以后的代码中不仅仅只有if else,那么到这里本文结束。

 参考

[浅析]特定场景下取代if-else和switch的方案

如何无痛降低 if else 面条代码复杂度

你本可以少写些 if-else

JavaScript 复杂判断的更优雅写法

提升代码幸福度,五个技巧减少js开发中的if else语句的更多相关文章

  1. VS 提升代码辨识度 (工欲善其事必先利其器)新手开发必备!

    VS简化编译.提高生产 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心创 ...

  2. JS开发中的一些小技巧和方法

    生成指定范围内的随机数 当我们需要获取指定范围(min,max)内的整数的时候,下面的代码非常适合:这段代码用的还挺多的. function setRadomNum(min,max){ return ...

  3. 【常用技巧】js开发的一些技巧

    1.console.log的特殊用法: 添加%c特殊符号即可打印出样式 console.log("%c djsakiasjdkasjdkjas","font-size:6 ...

  4. JS开发中的各大技巧

    「String Skill」:字符串技巧 「Number Skill」:数值技巧 「Boolean Skill」:布尔技巧 「Array Skill」:数组技巧 「Object Skill」:对象技巧 ...

  5. c#面向对象基础技能——学习笔记(五)委托技术在开发中的应用

    委托 delegate 1.是一种全新的面向对象语言的特性: 2.开发事件驱动程序变得非常简单: 3.简化多线程难度. 理解委托:可以理解成一个方法的指针.(接收的变量是方法) 步骤: 1.声明委托, ...

  6. JS开发中常用的小技巧

    1.获取指定范围内的随机数 1 2 3 function getRadomNum(min,max){     return  Math.floor(Math.random() * (max - min ...

  7. js开发中常用小技巧

    1.获取指定范围内的随机数 function getRadomNum(min,max){ return Math.floor(Math.random() * (max - min + 1)) + mi ...

  8. 解析Android开发优化之:从代码角度进行优化的技巧

    下面我们就从几个方面来了解Android开发过程中的代码优化,需要的朋友参考下   通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的.一般来说 ...

  9. OAF开发中一些LOV相关技巧 (转)

    原文地址:OAF开发中一些LOV相关技巧 在OAF开发中,LOV的使用频率是很高的,它由两部分构成一是页面上的LOV输入框(如OAMESSageLovInputBean),二是弹出的LOV模式窗口(O ...

随机推荐

  1. ASI中POST请求和文件下载

    //POST请求 1 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1.URL NSURL *url = ...

  2. Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)

    1 开发需要环境 工欲善其事,必先利其器.在正式开发之前我们检查好需要安装的拓展,不要开发中发现这些问题,打断思路影响我们的开发效率. 安装 swoole 拓展包 安装 redis 拓展包 安装 la ...

  3. java调用webservice,比较简单方便的方法。

    首先,请同学们自行了解webservice的基础知识. 个人理解,webservice约等于使用http+xml技术进行跨平台的数据交互. http和xml我们都很熟悉了,把他们两个组合到一起就是we ...

  4. 用launchscreen.storyboard适配启动图方法

    wwdc2019有session提出.到2020年4月,上架APP的启动图必须使用launchscreen.storyboard,不能再使用assert方式了.但是session没有给出如何适配.网上 ...

  5. 大型情感剧集Selenium:8_selenium网页截图的四种方法

    有时候,有时候,你会相信一切有尽头-当你的代码走到了尽头,那么保留最后一刻的状态尤为重要,此时你该如何操作?记录日志-没有将浏览器当前的状态进行截图来的直观! 那么,selenium截取截屏,有哪些方 ...

  6. 给一线讲产品·8期|VPC、子网、安全组,是什么关系?

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  7. idea object is not a member of package

    可能的原因: 1. pom.xml 依赖的工程没有deploy, 所有需要本地install改工程 2. 工程以来的库没有加入到 pom.xml中 3. 以上都没有问题,则右键该工程 => ma ...

  8. luogu P2759 奇怪的函数 |二分答案

    题目描述 使得 x^x达到或超过 n 位数字的最小正整数 x 是多少? 输入格式 一个正整数 n 输出格式 使得 x^x达到 n 位数字的最小正整数 x 计算一个数有多少位 log10(x)+1 #i ...

  9. 【Java Web开发学习】Spring构造器和属性注入

    测试类 public class Construct { private String address; private long phone; public Construct(String nam ...

  10. Runtime - 关联对象使用方法及注意点

    大家都知道在分类里,可以间接的添加属性,运用runtime关联对象. 如下图,只是声明了btnClickedCount的set, get方法而已 并没有生成_btnClickedCount 成员变量, ...