读高性能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书上的,所以强烈建议直接去看书而不是看我罗里吧嗦的几个字总结。
下一章将学习字符串和正则表达式很期待。
读高性能JavaScript编程 第四章 Conditionals的更多相关文章
- 读高性能JavaScript编程 第四章 Duff's Device
又要开始罗里吧嗦的 第四章 Summary 了. 这一次我尽量精简语言. 如果你认为 重复调用一个方法数次有点辣眼睛的话 比如: function test(i){ process(i++); pr ...
- 读高性能JavaScript编程 第三章
第三章 DOM Scripting 最小化 DOM 访问,在 JavaScript 端做尽可能多的事情. 在反复访问的地方使用局部变量存放 DOM 引用. 小心地处理 HTML 集合,因为他们表现 ...
- 读高性能JavaScript编程学英语 第一章第三页第一段话
When the browser encounters a <script> tag, as in this HTML page, there is no way of knowing w ...
- 读高性能JavaScript编程 第二章 让我知道了代码为什么要这样写
代码为什么要这样写? function initUI(){ var doc = document, bd = doc.body, links = doc.getElementsByTagName_r( ...
- 读高性能JavaScript编程 第一章
草草的看完第一章,虽然看的是译文也是感觉涨姿势了, 我来总结一下: 由于 大多数浏览器都是 single process 处理 ui updatas and js execute 于是产生问题: js ...
- 读《编写可维护的JavaScript》第四章总结
第四章 变量 函数和运算符 4.1 ① 变量声明 变量声明是通过var语句来完成的,并且所有的var语句都提前到包含这段逻辑的函数的顶部执行. function doSomething() { + v ...
- [转]Windows Shell 编程 第四章 【来源 http://blog.csdn.net/wangqiulin123456/article/details/7987933】
第四章 文件的本质 以前,所有文件和目录都有一个确定的属性集:时间,日期,尺寸,以及表示‘只读的’,‘隐藏的,‘存档的’,或‘系统的’状态标志.然而,Windos95(及后来的WindowsNT4.0 ...
- 高性能JavaScript 编程实践
前言 最近在翻<高性能JavaScript>这本书(2010年版 丁琛译),感觉可能是因为浏览器引擎的改进或是其他原因,书中有些原本能提高性能的代码在最新的浏览器中已经失效.但是有些章节的 ...
- Windows核心编程 第四章 进程(下)
4.3 终止进程的运行 若要终止进程的运行,可以使用下面四种方法: • 主线程的进入点函数返回(最好使用这个方法) . • 进程中的一个线程调用E x i t P r o c e s s函数(应该避免 ...
随机推荐
- 念念不忘,ASP.NET MVC显示WebForm网页或UserControl控件
学习与使用ASP.NET MVC这样久,还是对asp.net念念不忘.能否在asp.net mvc去显示aspx或是user control呢?这个灵感(算不上灵感,只能算是想法)是来自前些天有写过一 ...
- ADO.NET 【攻击及防御】
sql字符串注入攻击 SQL注入攻击是黑客对数据库进行攻击的常用手段之一.SQL注入的手法相当灵活 SQL注入攻击会导致的数据库安全风险包括:刷库.拖库.撞库. 一般来说,SQL注入一般存在于形如:H ...
- mongodb oplog与数据同步
1. 复制集(Replica sets)模式时,其会使用下面的local数据库local.system.replset 用于复制集配置对象存储 (通过shell下的rs.conf()或直接查询)loc ...
- Java虚拟机--虚拟机字节码执行引擎
Java虚拟机--虚拟机字节码执行引擎 所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 用于支持虚拟机进行方法调用和方 ...
- 逆向工程生成的mybatis中mapper文件。mapper接口,实例化成对象
逆向工程生成的mybatis中mapper文件中,*mapper文件只是接口,而不是类文件.但是却可以通过spring的容器获得实例. 例如: //1.获得mapper代理对象,从spring容器获得 ...
- 了解java虚拟机—JVM相关参数设置(2)
1. JVM相关参数设置 JVM相关配置 -XX:+PrintGC 两次次YoungGC,两次FullGC. -XX:+PrintGCDetails 打印GC时的内存,并且在程序结束时打印堆内存使 ...
- 利用netty简单实现聊天室
1.导入依赖包 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</a ...
- CentOS总结归纳之基本操作(linux系管与运维一)
原创作品,转载请在文章明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10170009.html 使用命令关闭和重启系统: 一.条件:只有root用户才 ...
- TCP连接与OKHTTP复用连接池
Android网络编程(八)源码解析OkHttp后篇[复用连接池] 1.引子 在了解OkHttp的复用连接池之前,我们首先要了解几个概念. TCP三次握手 通常我们进行HTTP连接网络的时候我们会进行 ...
- Dagger2 单例
解锁Dagger2使用姿势(二) 之带你理解@Scope Dagger2从0基础使用,到单例注入的正确姿势 Android之dagger2的简单运用和详细解读(入门)