`

JS优化原则

阅读更多

JS优化已经讨论了很多了,最近又看到aimingoo的一篇。大体上,aimingoo的说法都是非常正确的。 

除了像aimingoo做个案研究外,这里我想从更一般的角度总结在浏览器编程中JS优化的几个原则。 

首先,与其他语言不同,JS的效率很大程度是取决于JS engine的效率。除了引擎实现的优劣外,引擎自己也会为一些特殊的代码模式采取一些优化的策略。例如FF、Opera和Safari的JS引擎,都对字符串的拼接运算(+)做了特别优化。显然,要获得最大效率,就必须要了解引擎的脾气,尽量迎合引擎的口味。所以对于不同的引擎,所作的优化极有可能是背道而驰的。 

而如果做跨浏览器的web编程,则最大的问题是在于IE6(JScript 5.6)!因为在不打hotfix的情况下,JScript引擎的垃圾回收的bug,会导致其在真实应用中的performance跟其他浏览器根本不在一个数量级上。因此在这种场合做优化,实际上就是为JScript做优化! 

所以第一原则就是只需要为IE6(未打补丁的JScript 5.6或更早版本)做优化! 

如果你的程序已经优化到在IE6下可以接受的性能,那基本上在其他浏览器上性能就完全没有问题。 

因此,注意我下面讲的许多问题在其他引擎上可能完全不同,例如在循环中进行字符串拼接,通常认为需要用Array.join的方式,但是由于SpiderMonkey等引擎对字符串的“+”运算做了优化,结果使用Array.join的效率反而不如直接用“+”!但是如果考虑IE6,则其他浏览器上的这种效率的差别根本不值一提。 

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,而是通过对参数的显式判断来处理。 

比如: 

Java代码  收藏代码
  1. function sum() {  
  2.     var r = 0;  
  3.     for (var i = 0; i < arguments.length; i++) {  
  4.         r += arguments[i];  
  5.     }  
  6.     return r;  
  7. }  


这个sum通常调用的时候个数是较少的,我们希望改进它在参数较少时的性能。如果改成: 

Java代码  收藏代码
  1. function sum() {  
  2.     switch (arguments.length) {  
  3.         case 1return arguments[0];  
  4.         case 2return arguments[0] + arguments[1];  
  5.         case 3return arguments[0] + arguments[1] + arguments[2];  
  6.         case 4return arguments[0] + arguments[1] + arguments[2] + arguments[3];  
  7.         default:  
  8.             var r = 0;  
  9.             for (var i = 0; i < arguments.length; i++) {  
  10.                 r += arguments[i];  
  11.             }  
  12.             return r;  
  13.     }  
  14. }  


其实并不会有多少提高,但是如果改成: 

Java代码  收藏代码
  1. function sum(a, b, c, d, e, f, g) {  
  2.     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;  
  3.     if (g === undefined) return r;  
  4.     for (var i = 6; i < arguments.length; i++) {  
  5.         r += arguments[i];  
  6.     }  
  7.     return r;  
  8. }  


就会提高很多(至少快1倍)。 

最后是第五原则,也往往是真实应用中最重要的性能障碍,那就是尽量减少不必要的对象创建。 

本身创建对象是有一定的代价的,但是这个代价其实并不大。最根本的问题是由于JScript愚蠢之极的垃圾回收调度算法,导致随着对象个数的增加,性能严重下降(据微软的人自己说复杂度是O(n^2))。 

比如我们常见的字符串拼接问题,经过我的测试验证,单纯的多次创建字符串对象其实根本不是性能差的原因。要命的是在对象创建期间的无谓的垃圾回收的开销。而Array.join的方式,不会创建中间字符串对象,因此就减少了那该死的垃圾回收的开销。 

因此,如果我们能把大规模对象创建转化为单一语句,则其性能会得到极大的提高!例如通过构造代码然后eval——实际上PIES项目中正在根据这个想法来做一个专门的大规模对象产生器…… 

好了上面就是偶总结的JS优化五大原则。 

除了这些原则以外,还有一些特殊情况,如DOM的遍历。

 

 

关于DOM遍历:

如前所述,IE6 DOM中childNodes.length每次都是要遍历所有节点统计个数得出的。而childNodes[i]的访问,也要遍历直到第i个元素。所以在子节点数量巨大的情况下(超过1000),不宜使用for循环来遍历childNodes,否则会死得很惨。而应使用这样的遍历方法:

Java代码  收藏代码
  1. var node = elem.firstChild;  
  2. while (node != null) {  
  3.     ...  
  4.     node = node.nextSibling;  
  5. }  



另一个方式是使用IE自己的DHTML集合属性elem.children,但是它与childNodes不同,不包含文本节点。

 

 

本文转载自:http://www.iteye.com/topic/126859

分享到:
评论

相关推荐

    OLAP_OLTP优化.doc

    Oracle决策支持系统下的性能调整和优化原则

    seo网站优化步骤

    --形成关键词分析报告及布署方案 搜索引擎友好化---撰写站点修改措施建议书 内容强化---资讯频道建立、对编辑团队的培训 内部优化---URL优化、各级页面DIV重构、关键字布局、目录逻辑结构调整、JS优化、专题页建设等...

    javascript逆向 js混淆 乱码增强 js逆向学习

    在探索 JavaScript 逆向工程的过程中,建议遵循合法、道德的原则。学习逆向工程应该注重知识产权保护,尊重他人劳动成果。同时,倡导合法的学习途径,避免利用逆向工程技术从事非法活动。逆向工程是一个复杂而有挑战...

    JS学习资料

    本书在简洁明快地讲述JavaScript和DOM的基本知识之后,过几个实例演示了大师级的网页开发技术,并透彻阐述了一些至关重要的JavaScript编程原则和最佳实践,包括预留退路、循序渐进和以用户为中心等。读者可以非常...

    网站优化方案设计.doc

    12 2、网页标签优化 13 3、权重标签的替换 13 4、CSS、JS的调用 13 5、布局方法 13 (四)网页结构优化设计 13 1、网页内容优化 14 2、网页结构优化 15 (五)网站结构优化设计 15 二、搜索引擎优化方案设计 18 (一...

    Web开发者不可不知的15条编码原则

    但是,即便到现在,有很多基础的概念和原则依然需要开发者高度注意。下面,向大家介绍这些应该遵循的开发原则。  1、善用DIV来布局 ... 4、优化Javascript文件,并将其放到页面底部  5、善用标题元素

    高性能网站建设指南.pdf

    在本书中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。全书内容丰富,主要包括减少HTTP请求、EdgeComputing技术、ExpiresHeader技术、Gzip组件、CSS和JavaScript最佳实践、主页...

    《高性能网站建设指南》

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。全书内容丰富,主要包括减少HTTP请求、EdgeComputing技术、ExpiresHeader技术、Gzip组件、CSS和...

    SXWO符合搜索优化的全静态目录程序

    程序采用asp+access 的技术,由动态页面生成纯静态网站, 符合搜索优化原则,易于搜索引擎收录。可以随意增加、删除和修改类别和具体单个网站信息,操作简单, 发布快捷。 &lt;br&gt;网站描述支持HTML。 &lt;br&gt;特点:...

    《高性能网站建设指南》-- 想网站打开速度快,必看。

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    高性能网站建设指南和建设进阶指南

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    高性能网站建设指南(pdf).part3

    在本书中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。全书内容丰富,主要包括减少HTTP请求、EdgeComputing技术、ExpiresHeader技术、Gzip组件、CSS和JavaScript最佳实践、主页...

    高性能网站建设指南(pdf).part2

    在本书中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。全书内容丰富,主要包括减少HTTP请求、EdgeComputing技术、ExpiresHeader技术、Gzip组件、CSS和JavaScript最佳实践、主页...

    高性能网站建设指南(pdf).part1

    在本书中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。全书内容丰富,主要包括减少HTTP请求、EdgeComputing技术、ExpiresHeader技术、Gzip组件、CSS和JavaScript最佳实践、主页...

    《高性能网站建设指南》-- 中文版(2)

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    高性能网站建设指南

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    《高性能网站建设指南》-- 中文版(1)

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    构建高性能web站点 精选版

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    高性能网站建设指南.part2.rar

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

    高性能网站建设指南.part1.rar

    在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip...

Global site tag (gtag.js) - Google Analytics