• 读高性能JavaScript编程 第四章 Conditionals


     if else 和 switch    &&    递归  

    • if else 和 switch

      一般来说,if-else 适用于判断两个离散的值或者判断几个不同的值域。如果判断多于两个离散值,switch
    表达式将是更理想的选择。

      如同 我们在写sql 总习惯把可以过滤掉更多的where 放在前面一样,当 if else 判断的离散值较多时也因该这么干。

      二分搜索法:

     if (value == 0){  //要优化的代码
      return result0; 
    } else if (value == 1){ 
      return result1; 
    } else if (value == 2){ 
      return result2; 
    } else if (value == 3){ 
      return result3; 
    } else if (value == 4){ 
      return result4; 
    } else if (value == 5){ 
      return result5; 
    } else if (value == 6){ 
      return result6; 
    } else if (value == 7){ 
      return result7; 
    } else if (value == 8){ 
      return result8; 
    } else if (value == 9){ 
      return result9; 
    } else { 
      return result10; 
    } 
     if (value < 6){ //二分搜索法
      if (value < 3){ 
        if (value == 0){ 
          return result0; 
        } else if (value == 1){ 
          return result1; 
        } else { 
          return result2; 
        } 
      } else { 
        if (value == 3){ 
          return result3; 
        } else if (value == 4){ 
          return result4; 
        } else { 
          return result5; 
        } 
      } 
    } else { 
      if (value < 8){ 
        if (value == 6){ 
          return result6; 
        } else { 
          return result7; 
        } 
      } else { 
        if (value == 8){ 
          return result8; 
        } else if (value == 9){ 
          return result9; 
        } else { 
          return result10; 
        } 
      } 
    } 

    代码很简单 ,效果却很明显.

      查表法:

     //define the array of results 
    var results = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10] 
    //return the correct result 
    return results[value]; 

    更加简单暴力。

    • 递归

    引用:

      JavaScript引擎所支持的递归数量与 JavaScript调用栈大小直接相关。只有 Internet Explorer例外,它的
    调用栈与可用系统内存相关,其他浏览器有固定的调用栈限制。大多数现代浏览器的调用栈尺寸比老式浏
    览器要大(例如 Safari 2调用栈尺寸是 100)。图 4-2 显示出主流浏览器的调用栈大小。

    关于调用栈溢出错误,最令人感兴趣的部分大概是:在某些浏览器中,他们的确是 JavaScript 错误,可
    以用一个 try-catch 表达式捕获。异常类型因浏览器而不同。在 Firefox 中,它是一个 InternalError;在 Safari
    和 Chrome 中,它是一个 RangeError;在 Internet Explorer中抛出一个一般性的 Error类型。(Opera 不抛出
    错误;它终止 JavaScript引擎)。这使得我们能够在 JavaScript 中正确处理这些错误:
    try {
      recurse();
    } catch (ex){
      alert("Too much recursion!");
    }

      如果不管它,那么这些错误将像其他错误一样冒泡上传(在 Firefox中,它结束于 Firebug 和错误终端;
    在 Safari/Chrome 中它显示在 JavaScript 终端上),只有 Internet Explorer例外。IE 不会显示一个 JavaScript
    错误,但是会弹出一个提示堆栈溢出信息的对话框。

      大多数调用栈错误与递归有关。常见的栈溢出原因是一个不正确的终止条件,所以定位模式
    错误的第一步是验证终止条件。如果终止条件是正确的,那么算法包含了太多层递归,为了能够安全地在
    浏览器中运行,应当改用迭代,制表,或两者兼而有之。

       任何可以用递归实现的算法都可以用迭代实现。迭代算法通常包括几个不同的循环,分别对应算法过程

    的不同方面,也会导致自己的性能为题。但是,使用优化的循环替代长时间运行的递归函数可以提高性能,
    因为运行一个循环比反复调用一个函数的开销要低。

    优化递归的方案 制表

      一个经典的案例:

     function factorial(n){ 
      if (n == 0){ 
        return 1; 
      } else { 
        return n * factorial(n-1); 
      } 
    } 
    var fact6 = factorial(6); //factorial 计算阶乘
    var fact5 = factorial(5); 
    var fact4 = factorial(4); 

      此代码生成三个阶乘结果,factorial()函数总共被调用了 18次。此代码中最糟糕的部分是,所有必要的
    计算已经在第一行代码中执行过了。因为 6 的阶乘等于 6乘以 5 的阶乘,所以 5的阶乘被计算了两次。更
    糟糕的是,4的阶乘被计算了三次。更为明智的方法是保存并重利用它们的计算结果,而不是每次都重新
    计算整个函数。比如这样:

     function memfactorial(n){ 
      if (!memfactorial.cache){ 
        memfactorial.cache = { 
          "0": 1, 
          "1": 1 
        }; 
      } 
      if (!memfactorial.cache.hasOwnProperty(n)){ 
        memfactorial.cache[n] = n * memfactorial (n-1); 
      } 
      return memfactorial.cache[n]; 
    }

      var fact6 = memfactorial(6);
      var fact5 = memfactorial(5);
      var fact4 = memfactorial(4);

     //总共只调用 memfactorial()函数八次

    这样未免太过于繁琐,如果把制表的过程封装起来比如这样:

     function memoize(fundamental, cache){ 
      cache = cache || {}; 
      var shell = function(arg){ 
        if (!cache.hasOwnProperty(arg)){ 
          cache[arg] = fundamental(arg); 
        } 
        return cache[arg]; 
      }; 
      return shell; 
    } 
     //memoize the factorial function 
    var memfactorial = memoize(factorial, { "0": 1, "1": 1 }); 
    //call the new function 
    var fact6 = memfactorial(6); 
    var fact5 = memfactorial(5); 
    var fact4 = memfactorial(4); 

    需要提醒的是:当一个通用制表函数存在显著性能问题时,最好在这些函数中人工实现制表法。

     最后:运行的代码总量越大,使用这些策略所带来的性能提升就越明显。 代码全是copy书上的,所以强烈建议直接去看书而不是看我罗里吧嗦的几个字总结。

    下一章将学习字符串和正则表达式很期待。

  • 相关阅读:
    svn的revert、checkout、clean up、setting
    jsonp跨域原理
    王亚伟北大演讲:一切通胀问题都是货币问题(全文)
    string <-> wstring
    点在多边形内 经典算法(转)
    不可不表的OSG智能指针之强指针与弱指针 《转载》
    一个shell脚本给客户使用服务器生成一个序列号
    Rsync(远程同步): linux中Rsync命令的实际示例
    一个 rsync同步文件脚本
    用UltraISO制作CentOS U盘安装盘
  • 原文地址:https://www.cnblogs.com/zhuwansu/p/6146153.html
Copyright © 2020-2023  润新知