Skip to content

Latest commit

 

History

History
86 lines (84 loc) · 5.86 KB

代码优化与代码压缩.md

File metadata and controls

86 lines (84 loc) · 5.86 KB

###代码优化

  • 优化原则: > JS与其他语言不同在于它的执行效率很大程度是取决于JS engine的效率。除了引擎实现的优劣外,引擎自己也会为一些特殊的代码模式采取一些优化的策略。例如FFOperaSafariJAVASCRIPT引擎,都对字符串的拼接运算(+)做了特别优化。所以应该根据不同引擎进行不同优化。 > 而如果做跨浏览器的web编程,则最大的问题是在于IE6(JScript 5.6),因为在不打hotfix的情况下,JScript引擎的垃圾回收的bug,会导致其在真实应用中的performance跟其他浏览器根本不在一个数量级上。因此在这种场合做优化,实际上就是为JScript做优化,所以第一原则就是只需要为IE6(未打补丁的JScript 5.6或更早版本)做优化。
 - JS优化总是出现在大规模循环的地方:
 	这倒不是说循环本身有性能问题,而是循环会迅速放大可能存在的性能问题,所以第二原则就是以大规模循环体为最主要优化对象。
	以下的优化原则,只在大规模循环中才有意义,在循环体之外做此类优化基本上是没有意义的。
	目前绝大多数JS引擎都是解释执行的,而解释执行的情况下,在所有操作中,函数调用的效率是较低的。此外,过深的prototype继承链或者多级引用也会降低效率。JScript中,10级引用的开销大体是一次空函数调用开销的1/2。这两者的开销都远远大于简单操作(如四则运算)。
 - 尽量避免过多的引用层级和不必要的多次方法调用:
 	特别要注意的是,有些情况下看似是属性访问,实际上是方法调用。例如所有DOM的属性,实际上都是方法。在遍历一个NodeList的时候,循环 条件对于nodes.length的访问,看似属性读取,实际上是等价于函数调用的。而且IE DOM的实现上,childNodes.length每次是要通过内部遍历重新计数的。(My god,但是这是真的!因为我测过,childNodes.length的访问时间与childNodes.length的值成正比!)这非常耗费。所以 预先把nodes.length保存到js变量,当然可以提高遍历的性能。
	同样是函数调用,用户自定义函数的效率又远远低于语言内建函数,因为后者是对引擎本地方法的包装,而引擎通常是c,c++,java写的。进一步,同样的功能,语言内建构造的开销通常又比内建函数调用要效率高,因为前者在JS代码的parse阶段就可以确定和优化。
 - 尽量使用语言本身的构造和内建函数:
 	这里有一个例子是高性能的String.format方法。 String.format传统的实现方式是用String.replace(regex, func),在pattern包含n个占位符(包括重复的)时,自定义函数func就被调用n次。而这个高性能实现中,每次format调用所作的只是一次Array.join然后一次String.replace(regex, string)的操作,两者都是引擎内建方法,而不会有任何自定义函数调用。两次内建方法调用和n次的自定义方法调用,这就是性能上的差别。
	同样是内建特性,性能上也还是有差别的。例如在JScript中对于arguments的访问性能就很差,几乎赶上一次函数调用了。因此如果一个 可变参数的简单函数成为性能瓶颈的时候,可以将其内部做一些改变,不要访问arguments,而是通过对参数的显式判断来处理,比如:
	>
		function sum() {  
		    var r = 0;  
		    for (var i = 0; i < arguments.length; i++) {  
		        r += arguments[i];  
		    }  
		    return r;  
		}
	>
	这个sum通常调用的时候个数是较少的,我们希望改进它在参数较少时的性能。如果改成:
	>
		function sum() {  
		    switch (arguments.length) {  
		        case 1: return arguments[0];  
		        case 2: return arguments[0] + arguments[1];  
		        case 3: return arguments[0] + arguments[1] + arguments[2];  
		        case 4: return arguments[0] + arguments[1] + arguments[2] + arguments[3];  
		        default:  
		            var r = 0;  
		            for (var i = 0; i < arguments.length; i++) {  
		                r += arguments[i];  
		            }  
		            return r;  
		    }  
		}
	>
	其实并不会有多少提高,但是如果改成:
	>
		function sum(a, b, c, d, e, f, g) {  
		    var r = a ? b ? c ? d ? e ? f ? a + b + c + d + e + f : a + b + c + d + e : a + b + c + d : a + b + c : a + b : a : 0;  
		    if (g === undefined) return r;  
		    for (var i = 6; i < arguments.length; i++) {  
		        r += arguments[i];  
		    }  
		    return r;  
		}
	>
	就会提高很多(至少快1倍)。

###代码压缩

  • 代码压缩工具
>	精简代码就是将代码中的`空格`和`注释`去除,也有更进一步的会对变量名称`混淆`、`精简`。根据统计精简后文件大小会平均减少`21%`,即使`Gzip`之后文件也会减少`5%`。
- YUICompressor
- Dean Edwards Packer
- JSMin
- GZip压缩
	- `GZip`缩短在浏览器和服务器之间传送数据的时间,缩短时间后得到标题是`Accept-Encoding`: `gzip`,`deflate`的一个文件。不过这种压缩方法同样也有缺点。
		- 它在服务器端和客户端都要占用处理器资源(以便压缩和解压缩)。
		- 占用磁盘空间。
	- `Gzip`通常可以减少70%网页内容的大小,包括脚本、样式表、图片等任何一个文本类型的响应,包括`XML`和`JSON`。`Gzip`比`deflate`更高效,主流服务器都有相应的压缩支持模块。
	- `Gzip`的工作流程为
		- 客户端在请求`Accept-Encoding`中声明可以支持`Gzip`。
		- 服务器将请求文档压缩,并在`Content-Encoding`中声明该回复为`Gzip`格式。
		- 客户端收到之后按照`Gzip`解压缩。
- Closure compiler