• JS优化多分支结构(经典)


    分支结构的优化有很多好处:既方便代码维护,又可以提升代码执行效率。例如,设计有多个条件,只有当多个条件都成立时,才允许执行特定任务。

    示例1

    遵循简单的设计思路,使用多重分支逐个检测这些条件。

    1. if (a) {
    2. if (b) {
    3. if (c) {
    4. if (d) {console.log("所有条件都成立!"); }
    5. else {console.log("条件 d 不成立!"); }
    6. } else {console.log("条件 c 不成立!"); }
    7. } else {console.log("条件 b 不成立!"); }
    8. } else {console.log("条件 a 不成立!"); }

    示例2

    上述设计没有错误,结构嵌套合法。不过可以使用逻辑运算符进行优化。

    1. if (a && b && c && d) {console.log("所有条件都成立!"); }

    比较而言,使用 if 语句逐个检测每个条件的合法性,并对某个条件是否成立进行个性化处理,以方便跟踪。但是使用 if (a && b && c && d) 条件表达式,就没法进行过程跟踪。例如,如果 a 条件不成立,则程序会自动退出整个流程,而不管 b、c 和 d 的条件是否成立。这会使代码跟踪变得很困难。

    示例3

    优化设计思路,采用排除法,对每个条件逐一进行排除,如果全部成立则再执行特定任务。在排除过程中,使用一个标志变量把每一次条件检测联系在一起,最后根据这个标志变量决定是否完成特定任务。

    1. var t = true; //初始化标志变量为true
    2. if (! a) {
    3. console.log("条件 a 不成立!");
    4. t = false; //如果条件a不成立则标志变量为false
    5. }
    6. if (! b) {
    7. console.log("条件 b 不成立!");
    8. t = false; //如果条件a不成立则标志变量为false
    9. }
    10. if (! c) {
    11. console.log("条件 c 不成立!");
    12. t = false //如果条件a不成立则标志变量为false
    13. }
    14. if (! d) {
    15. console.log("条件 d 不成立!");
    16. t = false; //如果条件a不成立则标志变量为false
    17. }
    18. if (t) { //如果标志变量为true,则执行特定任务
    19. console.log("所有条件都成立!");
    20. }

    排除法有效避免了条件嵌套的复杂性,不过这种设计也存在一定的局限性,例如,一旦发生错误,后面的操作将被放弃。为此还可以再设计一个标志变量来跟踪错误。

    数据映射

    在多分支检测中,表达式的重复运算会影响性能。如果检测的条件满足下面两条,可以考虑使用数据映射来快速匹配,这样有助于代码的可读性,大大提高了代码的响应速度。

    • 条件体的数量庞大
    • 测试的条件值呈现离散状态

    实现方法:通过数组或普通对象实现。

    示例1

    在下面代码中,使用 switch 多分支检测离散值。

    1. function map(value) {
    2. switch (value) {
    3. case 0 : return "result0";
    4. case 1 : return "result1";
    5. case 2 : return "result2";
    6. case 3 : return "result3";
    7. case 4 : return "result4";
    8. case 5 : return "result5";
    9. case 6 : return "result6";
    10. case 7 : return "result7";
    11. case 8 : return "result8";
    12. case 9 : return "result9";
    13. default : return "result10"
    14. }
    15. }

    示例2

    针对示例 1 可以使用数组查询替代 switch 语句。下面代码把所有离散值存储到一个数组中,然后通过数组下标快速检测元素的值。

    1. function map(value) {
    2. var results = ["result0","result1","result2","result3","result4","result5",
    3. "result6","result7","result8","result9","result10"]
    4. return results[value];
    5. }

    使用数据映射法可以消除所有条件判断,但由于没有条件判断,当候选值数量增加时,基本不会增加额外的性能开销。

    如果每个键映射的不是简单的值,而是一系列的动作,则使用 switch 更适合。当然,也可以把这些动作包装在函数中,再把函数作为一个值与键进行映射。

    示例3

    如果条件查询中键名不是有序数字,则无法与数组下标映射,这时可以使用对象数据映射法。

    1. function map(value) {
    2. var results = {
    3. "a" : "result0","b" : "result1","c" : "result2","d" : "result3","e" : "result4","f" : "result5",
    4. "g" : "result6","h" : "result7","i" : "result8","j" : "resukt9","k" : "result10"
    5. }
    6. return results[value];
    7. }

    调整分支顺序

    在多分支结构中,各种条件存在先后、轻重的顺序。如果把最可能的条件放在前面,把最不可能的条件放在后面,那么程序被执行时总会按照代码先后顺序检测所有条件,直到发现匹配的条件时才停止。如果把最可能的条件放在前面,就等于降低了程序的检测次数,自然也就提升了分支结构的执行效率,避免空转。这在大批量数据检测中效果非常明显。

    示例1

    对于一个论坛系统来说,普通会员的数量要远远大于版主和管理员的数量。大部分登录的用户都是普通会员,如果把普通会员的检测放在分支结构的前面,就会减少每次检测的次数。

    1. switch (level) { //优化分支顺序
    2. case 1 :
    3. console.log("普通会员");
    4. break;
    5. case 2 :
    6. console.log("版主");
    7. break;
    8. case 3 :
    9. console.log("管理员");
    10. break;
    11. default :
    12. console.log("请登录");
    13. }

    在性能影响不大的情况下,遵循条件检测的自然顺序会更易于理解。

    示例2

    设计检测周一到周五值日任务安排的分支结构。可能周五的任务比较重要,或者周一的任务比较轻,但是对于这类有着明显顺序的结构,遵循自然顺序比较好。打乱顺序,把周五的任务安排在前面,对于整个分支结构的执行性能没有太大帮助,打乱的顺序不方便阅读。因此,按自然顺序来安排结构会更富有可读性。

    1. switch (day) {
    2. case 1 :
    3. console.log("周一任务安排");
    4. break;
    5. case 2 :
    6. console.log("周二任务安排");
    7. break;
    8. case 3 :
    9. console.log("周三任务安排");
    10. break;
    11. case 4 :
    12. console.log("周四任务安排");
    13. break;
    14. case 5 :
    15. console.log("周五任务安排");
    16. break;
    17. default :
    18. console.log("异常处理");
    19. }

    分支之间的顺序应注意优化,当然,对于同一个表达式内部也应该考虑逻辑顺序问题。由于逻辑与或逻辑或运算时,有可能会省略右侧表达式的计算,如果希望右侧表达式不管条件是否成立都被计算,就应该考虑逻辑顺序问题。

    示例3

    有两个条件 a 和 b,其中条件 a 多为真,而 b 是一个必须执行的表达式,那么下面逻辑顺序的设计就欠妥当。

    1. if (a && b) {
    2. //执行任务
    3. }

    如果条件 a 为 false,则 JavaScript 会忽略表达式 b 的计算。如果 b 表达式影响到后面的运算,则不执行表达式 b,自然会对后面的逻辑产生影响。因此,可以采用下面的设计思路,在 if 结构前先执行表达式 b,这样即使条件 a 的返回值为 false,也能够保证 b 表达式被计算。

    1. var c = b;
    2. if (a && b) {
    3. //执行任务
    4. }
  • 相关阅读:
    Web服务器-Tomcat详细原理与实现
    Github的2FA验证问题的丝滑解决方案 ||(Verify your two-factor authentication (2FA) settings)
    idea和jdk的安装教程
    【React源码】(十二)Hook源码分析 状态与副作用
    LeetCode每日一题(1717. Maximum Score From Removing Substrings)
    解决vue项目首行报红( ESLint 配置)和新建的vue文件首行报红问题
    Python A 组 G 题,全排列的价值 (AC)
    数字化转型专题汇总
    R语言两个时间序列数据的滞后相关性可视化:使用forecast包的ccf函数绘制交叉相关函数,根据可视化结果分析滞后相关性
    MySQL事务
  • 原文地址:https://blog.csdn.net/unbelievevc/article/details/128063290