本文是学习《高性能javascript》(Nichols C. Zakes著)的一些总结,虽然书比较过期,里面的知识点也有不少用不上了,可是毕竟是前人一步步探索过来的,记录着javascript艰难的发展历程,现在站在巨人的肩膀上,也许咱们也能发掘更好的javascript性能。javascript
第一章:加载和执行css
管理浏览器中的javascript代码是个棘手的问题,由于代码执行过程会阻塞浏览器的其余进程,好比用户界面绘制,每次遇到<script>标签,页面必须停下来等待代码下载(如外部连接文件)并执行,而后继续处理其余部分,尽管如此,仍是有几种方法能减小javascript对性能的影响。html
- <body/>闭合标签以前,将全部的<script>标签放到页面底部,这能确保在脚本执行前页面已经完成了渲染。
- 合并脚本,页面中全部的<script>标签越少,加载也就越快,响应也更迅速,不管外链文件仍是内部脚本都是如此。
- 有多种无阻塞的下载javascript的方法:
- 使用<script>标签的defer属性前端
- 使用动态建立的<script>元素来下载并执行代码java
- 使用XHR对象下载javascript代码并注入页面中web
第二章:数据访问ajax
在javascript中,数据存储的位置会对代码总体性能产生重大的影响。数据存储共有4种方式:直接量、变量、数组项、对象成员,它们有不一样的性能考虑。正则表达式
- 访问直接量和局部量的速度最快,相反,访问数组元素和对象成员相对较慢。
- 因为局部变量存在于做用域链的起始位置,所以访问局部变量比访问跨做用域变量更快,变量在做用域链的位置越深,访问所需的时间越长,因为全局变量总处在做用域链的最末端,所以访问速度也是最慢的。
- 避免使用with语句,由于它会改变运行期上下文做用域链。一样,try-catch语句中的catch子句也有一样的影响,所以要当心使用。
- 嵌套的对象成员会明显影响性能,尽可能少用。
- 属性或方法在原型链中的位置越深,访问它的速度越慢。
- 一般来讲,你能够经过把它经常使用的对象成员、数组元素、跨域变量保存在局部变量中来改善javascript的性能,由于局部变量访问速度更块。
第三章:DOM编程算法
访问和操做DOM是现代web应用的重要组成部分,但每次穿越链接ECMAScript和DOM两个岛屿之间的桥梁,都会被收取“过桥费”,为了减小DOM编程带来的性能损失,请记住如下几点:编程
- 最小化DOM访问次数,尽量在javascript中断处理。
- 若是须要屡次访问某个DOM节点,请使用局部变量存储它的引用。
- 当心处理HTML集合,由于它实时联系着底层文档,把集合的长度缓存到一个变量中,并在迭代中使用它,若是须要常常操做集合,建议把它拷贝到一个数组中。
- 若是可能的话,使用速度更快的API,好比querySelectorAll()和firstElementChild().
- 要留意重绘和重排,批量修改样式时,“离线”操做DOM树,使用缓存,并减小访问布局次数。
- 动画中使用绝对定位,使用拖放代理。
- 使用事件委托来减小事件处理器的数量。
第四章:算法和流程控制
如同其余编程语言,代码的写法和算法会影响javascript的运行时间,与其余语言不一样的是,javascript可用资源有限,所以优化技术更为重要。
- for、while和do-while循环性能特性类似,因此没有一种循环类型明显快于或慢于其余类型。
- 避免使用for-in循环,除非你须要遍历一个属性数量未知的对象。
- 改善循环性能的最佳方式是减小每次迭代的运算量和减小循环迭代次数。
- 一般来讲,switch总比if-else快,但并不老是最佳解决方案。
- 在判断条件较多时,使用查找表比if-else和switch快。
- 浏览器的调用栈大小限制了递归算法在javascript中的应用,栈溢出错误会致使其余代码中断运行。
- 若是你遇到栈溢出错误,可将方法改成迭代算法,或使用Memoization来避免重复计算。
- 运行的代码数量越大,使用这些策略所带来的性能提高也就越明显。
第五章:字符串和正则表达式
密集的字符串操做和草率的编写正则表达式可能产生严重的性能障碍,下面的方法助你避免常见的陷阱:
- 当链接数量巨大或尺寸巨大的字符串时,数组项链接是惟一在IE7及更早版本中性能合理的方法。
- 若是不考虑IE7及更早版本的性能,数组项链接是最慢的字符串链接方法之一,推荐使用简单的+和+=操做符代替,避免没必要要的中间字符串。
- 回溯既是正则表达式匹配功能的基本组成部分,也是正则表达式的低效之源。
- 回溯失控发生在正则表达式本应快速匹配的地方,但由于某些特殊的字符串匹配动做致使运行缓慢甚至浏览器崩溃。避免这个问题的办法是:使相邻的字元互斥,避免嵌套量词对同一字符串的相同部分屡次匹配,经过重复利用向前查看的原子组去除没必要要的回溯。
- 提升正则表达式效率的各类技术手段会有助于正则表达式更快的匹配,并在非匹配位置上花更少的时间。
- 正则表达式并不老是完成工做的最佳工具,尤为当你只搜索字面字符串的时候。
- 尽管有许多方法能够去除字符串的首尾空白,但使用两个简单的正则表达式(一个用来去头部,一个用来去除尾部)来处理大量字符串内容能提供一个简洁而跨浏览器的方法,从字符串末尾开始循环向前搜索第一个非空白字符,或者将此技术同正则表达式结合起来,会提供一个更好的替代方案,它不多受到字符串长度的影响。
第六章:快速响应的用户界面
javascript和用户界面更新在同一进程中运行,所以一次只能处理一件事情。这意味着当javascript代码正在运行时,用户界面不能响应输入,反之亦然,高效的管理UI线程就是要确保javascript不能运行太长时间,以避免影响用户体验,最后请牢记如下几点:
- 任何javascript任务都不该当执行超过100毫秒。过长的运行时间会致使UI更新出现明显的延迟,从而对用户体验产生负面影响。
- javascript运行期间,浏览器响应用户交互的行为存在差别,不管如何,javascript长时间运行将致使用户体验变得混乱和脱节。
- 定时器可用来安排代码延迟执行,它使得你能够把长时间运行脚本分解成一系列的任务。
- Web workers是新版浏览器支持的特性,它容许你在UI 线程外部执行javascript代码,从而避免锁定UI。
- web应用越复杂,积极主动的管理UI线程就越重要,没有什么javascript代码会重要到能够影响用户体验的程度。
第七章:AJAX
高性能的ajax包括如下几方面:了解你项目的具体需求,选择正确的数据格式和与之匹配的传输技术。
做为数据格式,纯文本和html只适用于特定场合,但它们能够节省客户端的CPU周期,XML被普遍应用并且支持良好,可是它十分笨重且解析缓慢,JSON是轻量级的,解析速度块(被视为原生代码而不是字符串),通用性与XML至关,字符分隔的自定义格式十分轻量,在解析大量数据集时很是快,但须要编写额外的服务端构造程序,并在客户端解析。
当从页面当前所处的域下请求数据时,XHR提供了最完美的控制和灵活性,尽管它会把接收到的全部数据当成一个字符串,且这有可能下降解析速度。另外一方面,动态脚本注入容许跨域请求和本地执行javascript和JSON可是它的接口不那么安全,并且还不能读取头信息或响应代码。Multipart XHR能够用来减小请求数,并处理一个响应中的各类文件类型,可是它不能缓存接收到的响应,当须要发送数据时,图片信息是一种简单而有效的方法,XHR还能够用POST方法发送大量数据。
除了这些格式和传输技术,还有一些准则有助于加速你的AJAX.
- 减小请求数,可经过合并javascript和css文件,或使用MXHR.
- 缩短页面的加载时间,页面主要内容加载完成时,用ajax获取那些次要的文件。
- 确保你的代码不会输出给用户,并在服务端处理错误。
- 知道什么时候使用成熟的ajax类库,以及什么时候编写本身的底层ajax代码。
第八章:编程实践
javascript提出了一些独一无二的性能挑战,这与你组织代码的方式有关。随着web应用变得愈来愈高级,包含的javascript代码愈来愈多,各类模式和反模式也逐渐出现,高效编程注意如下几点:
- 经过避免使用eval()和Function()构造器来避免双重求值带来的性能消耗,一样的,给setTimeout()和setInterval()传递函数而不是字符串做为参数。
- 尽可能使用直接量建立对象和数组,直接量的建立和初始化都比非直接变量形式要快。
- 避免作重复的工做,当须要检测浏览器时,可以使用延迟加载或条件预加载。
- 在进行数学计算时,考虑使用直接操做数字的二进制形式的位运算。
- javascript的原生方法总会比你写的任何代码都要快,尽可能使用原生方法。
第九章:构建并部署高性能的javascript应用
构建与部署的过程对基于javascript的web应用的性能有着巨大的影响。这个过程当中最重要的步骤有:
- 合并javascript文件以减小http请求数。
- 使用YUI Compressor压缩javascript文件。
- 在服务器端压缩javascript文件(Gzip编码)。
- 经过正确设置HTTP响应头来缓存javascript文件,经过向文件名增长时间戳来避免缓存问题。
- 使用CDN(Content Delivery Network)提供javascript文件,CDN不只能够提高性能,它也为你管理文件的压缩与缓存。
全部这些步骤都应该自动化处理,可使用一些公用的工具,也能够定置化工具来知足你的特定需求
第十章:工具
当网页或web应用变慢时,分析从网络下载的资源以及分析脚本的运行性能可以让你专一于那些最须要优化的地方。
- 使用网络分析工具找出加载脚本和页面中其余资源的瓶颈,这会帮助你决定哪些脚本须要延迟加载,或者须要进一步分析。
- 尽管传统的经验告诉咱们要尽可能减小HTTP请求数,但把脚本尽量延迟加载能够加快页面渲染速度,给用户带来更好的体验。
- 使用性能分析工具找出脚本运行时过程当中速度慢的地方,检查每一个函数所消耗的时间,以及函数被调用的次数,经过调用栈自身提供的一些线索来找出须要集中精力优化的地方。
- 尽管消耗的时间和调用次数一般是数据最有价值的部分,但仔细观察函数的调用过程,你也许会发现其余优化目标。
- 这些工具会帮助你深刻了解你的代码在那些一般你比较陌生的编程环境下是如何运行的,在开始优化工做以前先使用它们,以确保开发时间用在刀刃上。
这本书很快就读完了,基本讲的就是雅虎优化的十四条军规,虽然在现代大前端各类自动化工具的背景下,这些优化手段司空见惯,但在整个前端发展的道路上扮演了很重要的角色,现在有幸读到这本老书,受益不浅,并分享出来以此共勉。