对《30个提高Web程序执行效率的好经验》的理解

阅读了博客园发布的IT文章《30个提高Web程序执行效率的好经验》,这30条准则对我们web开发是非常有用的,不过大家可能对其中的一些准则是知其然而不知其所以然。

下面是我对这些准则的理解和分析,有些有关JS性能的准则,我也测试了它们的差异,大家可以下载DEMO页面,如有理解不正确的地方,请大家指正。也非常欢迎大家补充。

测试环境:

OS:Vista;

Processor:3.40GHz;

Memory: 2.00GB;

System type: 32-bit Operating System;

Browser: IE8, Forefox 3.5.7, Chrome4.0.249

   1. 尽量避免使用DOM。当需要反复使用DOM时,先把对DOM的引用存到JavaScript本地变量里再使用。使用设置innerHTML的方法来替换document.createElement/appendChild()方 法。

我们可以用如下的代码进行测试:

function testInnerHTML(){
var div1 = document.getElementById("testDiv");
var startTime = new Date();
var buf = new Array();
for (var n = 0; n < 5000; n ++){
buf.push('<a href="">test');
buf.push(n);
buf.push('</a>');
}
div1.innerHTML = buf.join('');
document.getElementById('divShowTime1').innerHTML = '耗时1:' +  (new Date() - startTime) + 'ms';
div1.innerHTML = "";
}
function testCreateElement(){
var div1 = document.getElementById("testDiv");
var startTime = new Date();
for (var n = 0; n < 5000; n ++){
var e = document.createElement('a');
e.href = '';
e.innerText = 'test' + n;
div1.appendChild(e);
}
document.getElementById('divShowTime2').innerHTML = '耗时2:' +  (new Date() - startTime) + 'ms';
div1.innerHTML = "";
}

 

测试结果:

 

  IE8 Firefox Chrome
1
耗时1:134ms

耗时2:857ms


耗时1:570ms

耗时2:658ms


耗时1:61ms

耗时2:47ms

2
耗时1:131ms

耗时2:846ms


耗时1:474ms

耗时2:610ms


耗时1:58ms

耗时2:48ms

3
耗时1:131ms

耗时2:927ms


耗时1:673ms

耗时2:674ms


耗时1:57ms

耗时2:49ms

4
耗时1:132ms

耗时2:846ms


耗时1:540ms

耗时2:686ms


耗时1:55ms

耗时2:46ms

测试结果显示使用innerHTML对比document.createElement/appendChild()方法,在IE8中,效率的提高是非常明显的,但是在Firefox和Chrome中,差别不大。

2. eval()有问题,new Fuction()构造函数也是,尽量避免使用它们。

eval方式比直接调用方式多了一步解析的过程,所以尽量避免使用它,如果必须用它,则最好是把调用的代码包装到函数中,然后eval这个函数,这样减少了解析的时间。eval函数的效率,我们可以用如下的代码测试:

 

function testNoEval() {
var startTime = new Date();
for(var i=0; i<500000; i++) {
var str = 'test';
}
var endTime = new Date();
document.getElementById('divShowTime1').innerHTML = '耗时1:' +  (endTime - startTime) + 'ms';
}
function testEval() {
var startTime = new Date();
eval("for(var i=0; i<500000; i++) { var str = 'test'; }");
var endTime = new Date();
document.getElementById('divShowTime2').innerHTML = '耗时2:' +  (endTime - startTime) + 'ms';
}

 

测试结果:

 

  IE8 Firefox Chrome
1
耗时1:85ms

耗时2:251ms


耗时1:2ms

耗时2:203ms


耗时1:1ms

耗时2:340ms

2
耗时1:82ms

耗时2:251ms


耗时1:2ms

耗时2:204ms


耗时1:2ms

耗时2:344ms

3
耗时1:81ms

耗时2:250ms


耗时1:2ms

耗时2:205ms


耗时1:1ms

耗时2:338ms

4
耗时1:82ms

耗时2:251ms


耗时1:2ms

耗时2:213ms


耗时1:2ms

耗时2:344ms

 

测试发现,eval的效率明显慢很多,尤其在Firefox和chrome中。 new Fuction的执行原理和eval类似,所以效率也是不高。

3. 拒绝使用with语句。 它会导致当你引用这个变量时去额外的搜索这样的一个命名空间,with里的代码在编译时期是完全未知的。

原因明确,不过使用with语句,代码会非常简洁,我个人还是经常使用这个语句的。

4. 使用for()循环替代for…in循 环。因为for…in循环在开始循环之前需要Script引擎创建一个含有所有可循环属性的 List,需要多检查一次。

原因明确,没有补充。

5. 把try-catch语句放在循环外面,不要放在循环里面,因为异常是很少发生的,放在外面避免每次都要执行 它们。

原因明确,这是我认为使用任何语言都有必要遵守的准则。

6. 甚至圣经里都提到过这个 – 不要全局的。全局变量的生命周期贯穿整个脚本的生命周期,而本地变量的存在范围随着本地命名空间的销毁而消失。当在函数或其它地方引用一个全局变量时,脚 本引擎需要搜索整个全局命名空间。

防止内存泄漏和提高查找解析速度,另外,变量定义在最小使用范围内,代码的可读性好。

7. fullName += 'John'; fullName += 'Holdings';执行速度快于fullName += 'John' + 'Holdings';

还是采用测试代码:

 

function testString1() {
var startTime = new Date();
for(var i=0; i<500000; i++) {
var fullName = "";
fullName += 'John';
fullName += 'Holdings';
}
var endTime = new Date();
document.getElementById('divShowTime1').innerHTML = '耗时1:' +  (endTime - startTime) + 'ms';
}
function testString2() {
var startTime = new Date();
for(var i=0; i<500000; i++) {
var fullName = "";
fullName += 'John' + 'Holdings';
}
var endTime = new Date();
document.getElementById('divShowTime2').innerHTML = '耗时2:' +  (endTime - startTime) + 'ms';
}

 

测试结果:

  IE8 Firefox Chrome
1
耗时1:492ms

耗时2:477ms


耗时1:151ms

耗时2:7ms


耗时1:52ms

耗时2:51ms

2
耗时1:532ms

耗时2:456ms


耗时1:150ms

耗时2:7ms


耗时1:50ms

耗时2:51ms

3
耗时1:493ms

耗时2:454ms


耗时1:148ms

耗时2:7ms


耗时1:53ms

耗时2:50ms

4
耗时1:491ms

耗时2:466ms


耗时1:204ms

耗时2:8ms


耗时1:51ms

耗时2:50ms

 

测试结果出乎意料,在IE8和chrome中,两者的效率差不多,但是在Firefox中,第一种写法反而比第二种慢很多。IE6下测试也是如此,看来这条规则还有待进一步研究。

8. 如果你需要把多个字符串连接起来,最好是把他们做成一个数组,然后调用join()方法实现这个操作。这种方式在生成HTML片段时尤其 有效。

验证还是用测试代码:

 

function testNoJoin(){
var startTime = new Date();
var testStr = "abcdefghqwertyuiolkjmzxv";
var result = "";
for(var i=0; i<50000; i++) result += testStr;
document.getElementById('divShowTime1').innerHTML = '耗时1:' +  (new Date() - startTime) + 'ms';
}
function testJoin(){
var startTime = new Date();
var testStr = "abcdefghqwertyuiolkjmzxv";
var result = "";
var strs = new Array();
for(var i=0; i<50000; i++) strs[i] = testStr;
result = strs.join("");
document.getElementById('divShowTime2').innerHTML = '耗时2:' +  (new Date() - startTime) + 'ms';
strs = null;
}

 

测试结果:

  IE8 Firefox Chrome
1
耗时1:19ms

耗时2:25ms


耗时1:25ms

耗时2:25ms


耗时1:15ms

耗时2:9ms

2
耗时1:28ms

耗时2:25ms


耗时1:24ms

耗时2:25ms


耗时1:16ms

耗时2:8ms

3
耗时1:17ms

耗时2:25ms


耗时1:25ms

耗时2:25ms


耗时1:4ms

耗时2:8ms

4
耗时1:16ms

耗时2:25ms


耗时1:28ms

耗时2:27ms


耗时1:4ms

耗时2:11ms

 

可以看出,这条规则在主流的浏览器中,效率的差别不大。IE6下测试,的确第一种比第二种方式效率差很多,所以这条规则已经过时了。

9. 对于简单的任务,最好使用基本操作方式来实现,而不是使用函数调用实现。例如val1 < val2 ? val1 : val2;执行速度快于Math.min(val1, val2);,类似的,myArr.push(newEle);慢于myArr[myArr.length] = newEle;

这条很好理解,原生态的好。

10. 将函数的引用作为参数传递到setTimeout()和setInterval()里优于将函数名作为字符串参数传递(硬编码)。例如,setTimeout(”someFunc()”, 1000)执行效率慢于setTimeout(someFunc, 1000)

道理类似如上的eval方式。

11. 当进行遍历操作时避免使用DOM操作。通过像getElementsByTagName()这 种方法得到的DOM元素队列都是动态的;有可能在你还没有对它遍历完成时,它已经被改变。这有可能导致死循环。

没有补充。

12. 当你对对象的成员(属性或方法)进行反复操作时,先存储对它们的引用。例如var getTags = document.getElementsByTagName; getTags(’div’);

这条规则的例子,我认为没有表达规则的意思,所以它举得例子不好。并且我按照它的例子测试,并没有发现两者的差异,所以我重新写测试代码如下:

 

function testMethod1() {
var startTime = new Date();
var tag = document.getElementById('testDiv');
for(var i=0; i<50000; i++) var color = tag.style.backgroundColor;
document.getElementById('divShowTime1').innerHTML = '耗时1:' +  (new Date() - startTime) + 'ms';
}
function testMethod2() {
var startTime = new Date();
for(var i=0; i<50000; i++) var color = document.getElementById('testDiv').style.backgroundColor;
document.getElementById('divShowTime2').innerHTML = '耗时2:' +  (new Date() - startTime) + 'ms';
}

 

测试结果:

  IE8 Firefox Chrome
1
耗时1:400ms

耗时2:1071ms


耗时1:115ms

耗时2:303ms


耗时1:28ms

耗时2:63ms

2
耗时1:404ms

耗时2:1081ms


耗时1:116ms

耗时2:298ms


耗时1:27ms

耗时2:63ms

3
耗时1:17ms

耗时2:25ms


耗时1:115ms

耗时2:287ms


耗时1:27ms

耗时2:62ms

4
耗时1:399ms

耗时2:1080ms


耗时1:119ms

耗时2:280ms


耗时1:29ms

耗时2:62ms

 

这个结果也很容易理解,毕竟多调用了一次取DOM函数!

13. 在任何的代码段里,在局部变量范围外存放一个这个局部变量的引用。例如

      function foo(arr) {

      var a = ’something’;

      //变量 ‘a’ 对于下面的一段就是范围外变量,这个变量的引用在很多情况下会有用处。

      for (var i = 0, j = a, loopLen = arr.length; i < loopLen; i++) {

      //do something

      }

      }

没有理解这段的主要意思。

14. for(var i=0; i < someArray.length; i++) {…}的执行效率慢于for (var i=0, loopLen=someArray.length; i<loopLen; i++) {…}。

例子如下:

 

function testLoop1() {
var someArray = new Array();
for (var i=0; i < 50000; i++) {
someArray.push(i);
}
var startTime = new Date();
for(var j=0; j < someArray.length; j++) var value = someArray[j];
document.getElementById('divShowTime1').innerHTML = '耗时1:' +  (new Date() - startTime) + 'ms';
}
function testLoop2() {
var someArray = new Array();
for (var i=0; i < 50000; i++) {
someArray.push(i);
}
var startTime = new Date();
for(var j=0,loopLen=someArray.length; j<loopLen; j++) var value = someArray[j];
document.getElementById('divShowTime2').innerHTML = '耗时2:' +  (new Date() - startTime) + 'ms';
}

 

这条也很好理解,第一种方式比第二种方式多了取Array长度的步骤。

15. 在HTTP头信息里加入缓存控制过期和最大存活时间标记。

没有补充

16. 优化CSS。要使用<link>方式,而不要使用@import方式。请参考这个优秀的文档http://www.slideshare.net/stubbornella/object-oriented-css

没有补充

17. 使用CSS技术来优化图片资源

减少图片链接个数,减少网络传输压力。

18. 用GZip方式压缩 .js 和 .css 文件。如果你使用的是Apache,在 .htaccess 里设置压缩方式,你的HTML, XML 和 JSON 也同时会被压缩。

AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml application/x-javascript application/json

减少传输的压力,增加响应速度。对小型站点,js和css文件不是很大,效果不明显。

19. 使用JavaScript压缩工具。除了使用YUI和JSMin外,你还可以试一试Google Closure http://closure-compiler.appspot.com/home (感谢: James Westgate, 一位读者)

和上面类似,现在有好多JS压缩和混淆的工具。

20. 优化每个页面上的各种资源,把它们拆分到各个子域上,这么它们就能够并行下载。请参考http://yuiblog.com/blog/2007/04/11/performance-research-part-4/

没有补充。

21. 将CSS样式表放在页面的最顶端,这样能方便包括IE在内的浏览器进行解析。

没有补充。

22. 尽量将DOM结构保持的越简单越好。DOM的体积会影响相关的操作效率,像查找, 遍历,DOM改动都有影响。document.getElementsByTagName(’*').length这 个值越小越好。

没有补充。

23. 注意你使用的选择器。例如,如果你想获取一个ul下的直接子元素,使用jQuery(”ul > li”)而不要使用jQuery(”ul li”)

更快的查找速度,遍历的元素少。

24. 当切换元素的可见性时(display),请记住:element.css({display:none})的 速度快于element.hide() 和 element.addClass(’myHiddenClass’)。 除非在一个循环里,我选择element.addClass(’myHiddenClass’), 这样会使代码更简洁 – 不要使用 inline CSS 和 JavaScript。

没有补充。

25. 当你使用完对DOM的引用变量后,要把它置为NULL。

资源回收。

26. 使用AJAX时,GET的执行效率高于POST。所以要尽量使用 GET 方式。只是要注意一点,IE只允许你用GET传送2K的数据。

同样的信息,GET方式传输,使用更少的数据量,所以用GET方式效率高。但是GET方式的安全性不高,传输的数据量受限制。

27. 小心使用脚本动画。没有硬件的支持,动画会执行的很慢。尽量避免使用那些没有实际价值的动画效果。

这是每个使用过脚本动画都深有体会的,不过,我认为HTML5中canvas会广泛地应用,canvas能做出令人赏心悦目的动画效果,值得大家关注。

28. 如果你的background-image对于这个图片的容器太小的话,请避免使 用background-repeat。如果你的背景图片需要来回填充很多次才能充满背景,那么将background-repeat属性设置成background-image 和repeat-x 或 repeat-y来 达到填充背景的效果的做法是不明智的,这种填充方式的效率特别的低。你应该尝试使用一个足够大的图片来做background-image并 且使用background-repeat: no-repeat。

好建议,没有补充

29. 布局时不要使用<table>。 <table>在浏览器完全把它画出来之前需要反复绘制好几次。因为DOM中<table>是很少见的一种之后输出的会影响之前输出的显示效果的元素。对于表格数据来说,你可 以使用table-layout:fixed; 这是一种更有效的现实算法,根据CSS 2.1技术说明,这种写法可以让表格一行一行的输出。

除了上面的原因外,table在样式继承,offset值计算上,在多浏览器中的表现上,都有不少诡异的差异,例如:如果在td中有个元素div,则取div的offsetParent返回是td元素,并不是我们期望的具有position属性的父元素。

30. 尽可能的使用原始JavaScript。限制JavaScript框架的使用。

这一条的准则,要看实际的情况,如果项目非常小,则如果使用框架,框架中大部分的code是没有用的,这样就额外增加了加载时间。如果是大型项目,则使用成熟框架,如Jquery等,不仅能减少开发时间和成本,也减少了后续维护的成本。

时间: 2024-09-21 04:46:04

对《30个提高Web程序执行效率的好经验》的理解的相关文章

30个提高Web程序执行效率的好经验分享_相关技巧

尽量避免使用DOM.当需要反复使用DOM时,先把对DOM的引用存到JavaScript本地变量里再使用.使用设置innerHTML的方法来替换document.createElement/appendChild()方 法. eval()有问题,new Fuction()构造函数也是,尽量避免使用它们. 拒绝使用with语句. 它会导致当你引用这个变量时去额外的搜索这样的一个命名空间,with里的代码在编译时期是完全未知的. 使用for()循环替代for-in循 环.因为for-in循环在开始循环

如何提高WEB程序的效率 (第一篇SQL篇)  (转)

web|程序 如何提高WEB程序的效率 (第一篇"SQL篇") 很多网友非常不喜欢用ASP来编程,他们总是抱怨说ASP程序太慢,效率太低.更希望用PHP,JSP等来写程序.其实不能从 "认为" 这个角度来看问题 ,而应该从实际中看问题,ASP真的很慢的吗,那么微软的站为何用ASP也不慢呢?PHP真的很快吗,其实它也仍然是解释性的语言.只不过在Linux下的结合比较好而以.JSP的开发也不会简单到何处,而且要通过JDBC-ODBC桥才能连接ACCESS库等,这种情况下

如何提高WEB程序的效率 (第一篇)

web|程序 很多网友非常不喜欢用ASP来编程,他们总是抱怨说ASP程序太慢,效率太低.更希望用PHP,JSP等来写程序.其实不能从 "认为" 这个角度来看问题 ,而应该从实际中看问题,ASP真的很慢的吗,那么微软的站为何用ASP也不慢呢?PHP真的很快吗,其实它也仍然是解释性的语言.只不过在Linux下的结合比较好而以.JSP的开发也不会简单到何处,而且要通过JDBC-ODBC桥才能连接ACCESS库等,这种情况下效率也不高. 其实,三种语言各有特点,就是优,缺点.作为一个程序员不应

如何提高WEB程序的效率

web|程序 很多网友非常不喜欢用ASP来编程,他们总是抱怨说ASP程序太慢,效率太低.更希望用PHP,JSP等来写程序.其实不能从 "认为" 这个角度来看问题 ,而应该从实际中看问题,ASP真的很慢的吗,那么微软的站为何用ASP也不慢呢?PHP真的很快吗,其实它也仍然是解释性的语言.只不过在Linux下的结合比较好而以.JSP的开发也不会简单到何处,而且要通过JDBC-ODBC桥才能连接ACCESS库等,这种情况下效率也不高. 其实,三种语言各有特点,就是优,缺点.作为一个程序员不应

提高ASP页面执行效率的方法分析_应用技巧

这些大都是与硬件相关.其实在软件上,好的程序设计的方法和正确的参数配置也可以提高程序的性能,有时 在同等情况下只要改变一个参数,程序执行效率就能大大提高.本文就试着在这方面做些探索. 一.影响性能的因素 ASP程序运行的性能主要决定于以下2个大方面: 1.HTML页面的执行效率 2.反应时间,其中反应时间主要受制于下面要素: (1).ASP页面的执行效率 (2).数据库因素 下面我们就来详细讨论一下. 二.详细讨论 1.影响HTML的因素 HTML页面的执行效率是一个纯客户端的问题.影响这个问题

提高ASP页面执行效率的方法分析

这些大都是与硬件相关.其实在软件上,好的程序设计的方法和正确的参数配置也可以提高程序的性能,有时 在同等情况下只要改变一个参数,程序执行效率就能大大提高.本文就试着在这方面做些探索. 一.影响性能的因素 ASP程序运行的性能主要决定于以下2个大方面: 1.HTML页面的执行效率 2.反应时间,其中反应时间主要受制于下面要素: (1).ASP页面的执行效率 (2).数据库因素 下面我们就来详细讨论一下. 二.详细讨论 1.影响HTML的因素 HTML页面的执行效率是一个纯客户端的问题.影响这个问题

教你用Type Hint提高Python程序开发效率_python

简介 Type Hint(或者叫做PEP-484)提供了一种针对Python程序的类型标注标准. 为什么使用Type Hint?对于动态语言而言,常常出现的情况是当你写了一段代码后,隔段时间你可能忘记这个方法的原型是什么样子的了,你也不清楚具体应该传入什么类型的参数,这样往往需要你去阅读代码才能定义每个类型具体是什么.或者当你使用一个文档并不是特别完全的第三方库,你不知道这个库应该如何使用,这都会很痛苦. 现在,借助Type Hint,你可以实现:      1.实现类型检查,防止运行时出现的类

作为SEOer必须提高SEO的执行效率

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 对于如何做好SEO工作,提升网站综合排名是每一位站长都在关注的事情.站长们每天都会查看自己的网站流量和来路,并且会分析竞争对手的网站收录以及排名情况,但最让站长头疼的就是如何提高网站排名如何超越竞争对手.对于这点大部分站长的回答就是做外链更新原创内容,这也是绝大部分站长必须做的,但是每个站长的情况不同所以就出现了执行力和执行效率的问题,今天分

提高Java程序内存效率

程序 我们都知道Java程序之所以被广大程序员青睐,很大的一个原因是因为Java有GC(垃圾收集),不用程序员花很大的精力来解决内存释放和泄漏问题.而这些问题总是C/C++程序员需要花很大精力来认真地面对的. 问题总是双面的,GC给我们带来了很大的快乐,释放了程序员很多的精力和时间,但是在某些时候也会给我们带来一些小小的麻烦.Java里的Object并非交给GC去释放就可高枕无忧了,下面从JDK1.4的Demo中Java2D的Memory Monitor说起. 先看看Memory Monitor