JavaScript提升性能的常用技巧总结【经典】
本文讲述了JavaScript提升性能的常用技巧。分享给大家供大家参考,具体如下:
1.注意作用域
随着作用域链中的作用域数量的增加,访问当前作用域以外的变量的时间也在增加.访问全局变量总是要比访问局部变量慢,因为要遍历作用域链.
1).避免全局查找 将在一个函数中会多次用到的全局对象存储为局部变量总是没错的.
2).避免with语句 with会创建自己的作用域,因此会增加其中执行代码的作用域链的长度.
2.选择正确的方法
性能问题的一部分是和用于解决问题的算法或者方法有关的.
1).避免不必要的属性查找
在计算机科学中,算法的复杂度是使用O符号来表示的.最简单,最快捷的算法是常数值,即O(1).之后,算法变得越来越复杂并花更长时间执行.常用的JavaScript算法类型有:
常数:不管有多少值,执行的时间都是恒定的.一般表示简单值和存储在变量的值.
对数:总的执行时间和值的数量相关,但是要完成算法并不一定要获取每个值.例如:二分查找
线性:总执行时间和值的数量直接相关.例如:遍历某个数组中的所有元素
平方:总执行时间和值的数量有关,每个值至少要获取n次.例如:插入排序
立方: 总执行时间和值的数量有关,每个值至少要获取n的平方次
使用变量和数组要比访问对象上的属性更有效率.对象上的任何属性的查找都要比访问变量或者数组花更长时间,因为必须在原型链中对拥有该名称的属性进行一次搜索.
一般来讲,只要能减少算法的复杂度,就要尽可能减少.尽可能多地使用局部变量将属性查找替换为值查找.进一步讲,如果即可以用数字化的数组位置进行访问,也可以使用命名属性(诸如NodeList对象),那么使用数组位置.
2).优化循环
a.减值迭代 在很多情况下,从最大值开始,在循环中不断减值的迭代器更加高效.
b.简化终止条件 由于每次循环过程都会计算终止条件,所以必须保证它尽可能快.
c.简化循环体 循环体是执行最多的,所以要确保其被最大限度地优化.确保没有某些可以被很容易移出循环的密集计算.
d.使用后测试循环 最常用的for循环和while循环都是前测试循环.而如do-while这种后测试循环,可以避免最初终止条件的计算,因此更快.
3).展开循环 当循环的次数是确定的,消除循环并使用多次函数调用往往更快.如著名的Duff装置
4).避免双重解释
当JavaScript代码想解析JavaScript的时候就会存在双重解释的惩罚.如下例:
eval("alert('Helloworld!')"); //某些代码求值
修正:
alert('Helloworld');
varsayHi=newFunction("alert('Helloworld!')");
修正:
varsayHi=function(){ alert("Hellowworld!'); };
setTimeout("alert('Hellowworld!')",500);
修正:
setTimeout(function)({ alert('Hellowworld!'); },500);
5).其他方法
原生方法较快--只要有可能,使用原生方法而不是自己用JavaScript重写一个.原生方法是用诸如C/C++之类的编译型语言写出来的,所以要比JavaScript的快很多很多.JavaScript中最容易被忘记的就是可以在Math对象中找到的复杂的数学运算;这些方法要比任何用JavaScript写的同样方法,如正弦,余弦快的多.
Switch语句较快--如果有一系复杂的if-else语句,可以转换成单个switch语句则可以得到更快的代码.还可以通过将case语句按最可能的到最不可能在顺序进行组织,来进一步优化switch语句.
位运算符较快--当进行数学运算的时候,位运算操作要比任何布尔运算或者算数运算快.选择性的用位运算换算数运算可以极大提升复杂计算的性能.诸如取模,逻辑与和逻辑或都可以考虑用位运算来替换.
3.最小化语句数
1).多个变量声明
如:
//4个语句---很浪费 varcount=5; varcolor="blue"; varvalues=[1,2,3]; varnow=newDate();
优化:
varcount=5, color="blue", values=[1,2,3], noiw=newDate();
在大多数情况下这种优化都非常容易做,并且要比单个变量分别声明快很多.
2).插入迭代值
如:
varname=values[i]; i++;
优化:
varname=values[i++];
3).使用数组和对象字面量
如:
varvalues=newArray();---> varvalues=[];
varobj=newObject();--->varobj={};
4.优化DOM交互
1).最小化现场更新
一旦你需要访问DOM部分是已经显示的页面的一部分,那么你就是在进行一个现场更新.之所以叫现场更新,是因为需要立即(现场)对页面对用户的显示进行更新.不管是插入单个字符,还是移除整个片段,都有一个性能惩罚,因为浏览器要重新计算无数尺寸以进行更新.
例:
varlist=document.getElementById("myList"); for(vari=0;i<10;i++){ varitem=document.createElement("li"); list.appendChild(item); item.appendChild(document.createTextNode("Item"+i)); }
这样添加10个项目,这个操作总共要完成20个现场更新. 下面用创建文档碎片的方法改进:
varlist=document.getElementById("myList"); varfragment=document.createDocumentFragment(); for(vari=0;i<10;i++){ fragment.appendChild(item); item.appendChild(document.createTextNode("Item"+i)); } list.appendChlid(fragment);
在这个例子中只有一次现场更新,它发生在所有项目都创建好之后.文档碎片用作一个临时的占位符,放置新创建的项目.然后使用appendChild()将所有项目添加到列表用.记住,当给appendChild()传入文档碎片时,只有碎片中的子节点被添加到目标,碎片本身不会被添加的.
一旦需要更新DOM,请考虑使用文档碎片来构建DOM结构,然后将其添加到现存的文档中.
2).使用innerHTML
有两种在页面上创建DOM节点的方法:使用诸如createElement(),appendChild()之类的DOM方法,以及使用innerHTML对于小的DOM更改而言,两种方法效率都差不多.而对于大的DOM更改,使用innerHTML要比使用标准DOM方法创建同样的DOM结构快很多.同样,一次使用innerHTML比多次使用innerHTML也要快相当多.
3).使用事件代理(简,略)
4).注意NodeList
最小化访问NodeList的次数可以极大的改进脚本的性能.
发生以下情况时会返回NodeList对象:
a.进行了对getElementsByTagName()的调用
b.获取了元素的childNodes属性
c.获取了元素的attributes属性
d.访问了特殊的集合,如document.forms , document.images等等
要了解当使用NodeList对象时,合理使用会极大提升代码执行速度.
前面介绍的函数节流 也是很重要的一方面。特别是多重循环,非常耗性能时,此方法很有用的。
PS:对于javascript进行压缩,减少代码体积也是提升javascript性能的有效途径。这里就为大家推荐2款非常实用的压缩工具:
JavaScript压缩/格式化/加密工具:
http://tools.jb51.net/code/jscompress
jsmin在线js压缩工具:
http://tools.jb51.net/code/jsmincompress
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript切换特效与技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript动画特效与技巧汇总》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。