if else 和 switch    &&    递归

  • if else 和 switch

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

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

  二分搜索法:

  1. if (value == 0){ //要优化的代码
  2. return result0;
  3. } else if (value == 1){
  4. return result1;
  5. } else if (value == 2){
  6. return result2;
  7. } else if (value == 3){
  8. return result3;
  9. } else if (value == 4){
  10. return result4;
  11. } else if (value == 5){
  12. return result5;
  13. } else if (value == 6){
  14. return result6;
  15. } else if (value == 7){
  16. return result7;
  17. } else if (value == 8){
  18. return result8;
  19. } else if (value == 9){
  20. return result9;
  21. } else {
  22. return result10;
  23. }
  1. if (value < 6){ //二分搜索法
  2. if (value < 3){
  3. if (value == 0){
  4. return result0;
  5. } else if (value == 1){
  6. return result1;
  7. } else {
  8. return result2;
  9. }
  10. } else {
  11. if (value == 3){
  12. return result3;
  13. } else if (value == 4){
  14. return result4;
  15. } else {
  16. return result5;
  17. }
  18. }
  19. } else {
  20. if (value < 8){
  21. if (value == 6){
  22. return result6;
  23. } else {
  24. return result7;
  25. }
  26. } else {
  27. if (value == 8){
  28. return result8;
  29. } else if (value == 9){
  30. return result9;
  31. } else {
  32. return result10;
  33. }
  34. }
  35. }

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

  查表法:

  1. //define the array of results
  2. var results = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10]
  3. //return the correct result
  4. 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
错误,但是会弹出一个提示堆栈溢出信息的对话框。

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

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

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

优化递归的方案 制表

  一个经典的案例:

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

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

  1. function memfactorial(n){
  2. if (!memfactorial.cache){
  3. memfactorial.cache = {
  4. "0": 1,
  5. "1": 1
  6. };
  7. }
  8. if (!memfactorial.cache.hasOwnProperty(n)){
  9. memfactorial.cache[n] = n * memfactorial (n-1);
  10. }
  11. return memfactorial.cache[n];
  12. }

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

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

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

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

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

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

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

读高性能JavaScript编程 第四章 Conditionals的更多相关文章

  1. 读高性能JavaScript编程 第四章 Duff's Device

    又要开始罗里吧嗦的 第四章  Summary 了. 这一次我尽量精简语言. 如果你认为 重复调用一个方法数次有点辣眼睛的话 比如: function test(i){ process(i++); pr ...

  2. 读高性能JavaScript编程 第三章

    第三章  DOM Scripting  最小化 DOM 访问,在 JavaScript 端做尽可能多的事情. 在反复访问的地方使用局部变量存放 DOM 引用. 小心地处理 HTML 集合,因为他们表现 ...

  3. 读高性能JavaScript编程学英语 第一章第三页第一段话

    When the browser encounters a <script> tag, as in this HTML page, there is no way of knowing w ...

  4. 读高性能JavaScript编程 第二章 让我知道了代码为什么要这样写

    代码为什么要这样写? function initUI(){ var doc = document, bd = doc.body, links = doc.getElementsByTagName_r( ...

  5. 读高性能JavaScript编程 第一章

    草草的看完第一章,虽然看的是译文也是感觉涨姿势了, 我来总结一下: 由于 大多数浏览器都是 single process 处理 ui updatas and js execute 于是产生问题: js ...

  6. 读《编写可维护的JavaScript》第四章总结

    第四章 变量 函数和运算符 4.1 ① 变量声明 变量声明是通过var语句来完成的,并且所有的var语句都提前到包含这段逻辑的函数的顶部执行. function doSomething() { + v ...

  7. [转]Windows Shell 编程 第四章 【来源 http://blog.csdn.net/wangqiulin123456/article/details/7987933】

    第四章 文件的本质 以前,所有文件和目录都有一个确定的属性集:时间,日期,尺寸,以及表示‘只读的’,‘隐藏的,‘存档的’,或‘系统的’状态标志.然而,Windos95(及后来的WindowsNT4.0 ...

  8. 高性能JavaScript 编程实践

    前言 最近在翻<高性能JavaScript>这本书(2010年版 丁琛译),感觉可能是因为浏览器引擎的改进或是其他原因,书中有些原本能提高性能的代码在最新的浏览器中已经失效.但是有些章节的 ...

  9. Windows核心编程 第四章 进程(下)

    4.3 终止进程的运行 若要终止进程的运行,可以使用下面四种方法: • 主线程的进入点函数返回(最好使用这个方法) . • 进程中的一个线程调用E x i t P r o c e s s函数(应该避免 ...

随机推荐

  1. 念念不忘,ASP.NET MVC显示WebForm网页或UserControl控件

    学习与使用ASP.NET MVC这样久,还是对asp.net念念不忘.能否在asp.net mvc去显示aspx或是user control呢?这个灵感(算不上灵感,只能算是想法)是来自前些天有写过一 ...

  2. ADO.NET 【攻击及防御】

    sql字符串注入攻击 SQL注入攻击是黑客对数据库进行攻击的常用手段之一.SQL注入的手法相当灵活 SQL注入攻击会导致的数据库安全风险包括:刷库.拖库.撞库. 一般来说,SQL注入一般存在于形如:H ...

  3. mongodb oplog与数据同步

    1. 复制集(Replica sets)模式时,其会使用下面的local数据库local.system.replset 用于复制集配置对象存储 (通过shell下的rs.conf()或直接查询)loc ...

  4. Java虚拟机--虚拟机字节码执行引擎

    Java虚拟机--虚拟机字节码执行引擎 所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 用于支持虚拟机进行方法调用和方 ...

  5. 逆向工程生成的mybatis中mapper文件。mapper接口,实例化成对象

    逆向工程生成的mybatis中mapper文件中,*mapper文件只是接口,而不是类文件.但是却可以通过spring的容器获得实例. 例如: //1.获得mapper代理对象,从spring容器获得 ...

  6. 了解java虚拟机—JVM相关参数设置(2)

    1.   JVM相关参数设置 JVM相关配置 -XX:+PrintGC 两次次YoungGC,两次FullGC. -XX:+PrintGCDetails 打印GC时的内存,并且在程序结束时打印堆内存使 ...

  7. 利用netty简单实现聊天室

    1.导入依赖包 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</a ...

  8. CentOS总结归纳之基本操作(linux系管与运维一)

    原创作品,转载请在文章明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10170009.html 使用命令关闭和重启系统: 一.条件:只有root用户才 ...

  9. TCP连接与OKHTTP复用连接池

    Android网络编程(八)源码解析OkHttp后篇[复用连接池] 1.引子 在了解OkHttp的复用连接池之前,我们首先要了解几个概念. TCP三次握手 通常我们进行HTTP连接网络的时候我们会进行 ...

  10. Dagger2 单例

    解锁Dagger2使用姿势(二) 之带你理解@Scope Dagger2从0基础使用,到单例注入的正确姿势 Android之dagger2的简单运用和详细解读(入门)