sum+=arr;
}
优化后:
vararr=[1,2,3,4,5,6,7];
varsum=0,l=arr.length;
while(l--){
sum+=arr[l];
}
1.4条件分支
1.4.1将条件分支,按可能性顺序从高到低排列
说明:
可以减少解释器对条件的探测次数。
1.4.2在同一条件子的多(>2)条件分支时,使用switch优于if
说明:
switch分支选择的效率高于if,在IE下尤为明显。
4分支的测试,IE下switch的执行时间约为if的一半。
1.4.3使用三目运算符替代条件分支
优化前:
if(a>b){
num=a;
}else{
num=b;
}
优化后:
num=a>b?
a:
b;
1.5定时器
1.5.1需要不断执行的时候,优先考虑使用setInterval
说明:
setTimeout每一次都会初始化一个定时器。
setInterval只会在开始的时候初始化一个定时器
优化前:
vartimeoutTimes=0;
functiontimeout(){
timeoutTimes++;
if(timeoutTimes<10){
setTimeout(timeout,10);
}
}
timeout();
优化后:
varintervalTimes=0;
functioninterval(){
intervalTimes++;
if(intervalTimes>=10){
clearInterval(interv);
}
}
varinterv=setInterval(interval,10);
1.5.2使用function而不是string
说明:
如果把字符串作为setTimeout和setInterval的参数,浏览器会先用这个字符串构建一个function。
优化前:
varnum=0;
setTimeout('num++',10);
优化后:
varnum=0;
functionaddNum(){
num++;
}
setTimeout(addNum,10);
1.6其他
1.6.1尽量不使用动态语法元素
说明:
eval、Function、execScript等语句会再次使用javascript解析引擎进行解析,需要消耗大量的执行时间。
1.6.2重复使用的调用结果,事先保存到局部变量
说明:
避免多次取值的调用开销。
优化前:
varh1=element1.clientHeight+num1;
varh2=element1.clientHeight+num2;
优化后:
vareleHeight=element1.clientHeight;
varh1=eleHeight+num1;
varh2=eleHeight+num2;
1.6.3使用直接量
说明:
vara=newArray(param,param,...)->vara=[]
varfoo=newObject()->varfoo={}
varreg=newRegExp()->varreg=/.../
1.6.4避免使用with
说明:
with虽然可以缩短代码量,但是会在运行时构造一个新的scope。
OperaDev上还有这样的解释,使用with语句会使得解释器无法在语法解析阶段对代码进行优化。
对此说法,无法验证。
优化前:
with(a.b.c.d){
property1=1;
property2=2;
}
优化后:
varobj=a.b.c.d;
obj.property1=1;
obj.property2=2;
1.6.5巧用||和&&布尔运算符
优化前:
functioneventHandler(e){
if(!
e)e=window.event;
}
优化后:
functioneventHandler(e){
e=e||window.event;
}
优化前:
if(myobj){
doSomething(myobj);
}
优化后:
myobj&&doSomething(myobj);
1.6.6类型转换
说明:
1). 数字转换成字符串,应用""+1,性能上:
(""+)>String()>.toString()>newString();
2). 浮点数转换成整型,不使用parseInt(),parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,建议使用Math.floor()或者Math.round()
3). 对于自定义的对象,推荐显式调用toString()。
内部操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String。
1.6.7多用id,少用class
JS在IE浏览器下的效率并不好,尤其当页面很大且具有繁杂的逻辑操作时
在写html时,如果使用id,JS会很快在一次遍历中找到需要的元素(无论有几个id它都会在找到第一个id后返回)。
而通过class等去寻找,程序会在整个文档中一遍又一遍的去遍历,找到一个比较判断以后再去找第二个第三个……非常浪费资源。
2内存管理
2.1循环引用
说明:
如果循环引用中包含DOM对象或者ActiveX对象,那么就会发生内存泄露。
内存泄露的后果是在浏览器关闭前,即使是刷新页面,这部分内存不会被浏览器释放。
简单的循环引用:
varel=document.getElementById('MyElement');
varfunc=function(){…}
el.func=func;
func.element=el;
但是通常不会出现这种情况。
通常循环引用发生在为dom元素添加闭包作为expendo的时候。
如:
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=function(){……}
}
init();
init在执行的时候,当前上下文我们叫做context。
这个时候,context引用了el,el引用了function,function引用了context。
这时候形成了一个循环引用。
下面2种方法可以解决循环引用:
2.1.1 置空dom对象
优化前:
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=function(){……}
}
init();
优化后:
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=function(){……}
el=null;
}
init();
将el置空,context中不包含对dom对象的引用,从而打断循环应用。
如果我们需要将dom对象返回,可以用如下方法:
优化前:
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=function(){……}
returnel;
}
init();
优化后:
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=function(){……}
try{
returnel;
}finally{
el=null;
}
}
init();
2.1.2构造新的context
优化前:
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=function(){……}
}
init();
优化后:
functionelClickHandler(){……}
functioninit(){
varel=document.getElementById('MyElement');
el.onclick=elClickHandler;
}
init();
把function抽到新的context中,这样,function的context就不包含对el的引用,从而打断循环引用。
2.2通过javascript创建的dom对象,必须append到页面中
说明:
IE下,脚本创建的dom对象,如果没有append到页面中,刷新页面,这部分内存是不会回收的!
示例代码:
functioncreate(){
vargc=document.getElementById('GC');
for(vari=0;i<5000;i++)
{
varel=document.createElement('div');
el.innerHTML="test";
//下面这句可以注释掉,看看浏览器在任务管理器中,点击按钮然后刷新后的内存变化
gc.appendChild(el);
}
}
2.3释放dom元素占用的内存
说明:
将dom元素的innerHTML设置为空字符串,可以释放其子元素占用的内存。
在rich应用中,用户也许会在一个页面上停留很长时间,可以使用该方法释放积累得越来越多的dom元素使用的内存。
2.4释放javascript对象
说明:
在rich应用中,随着实例化对象数量的增加,内存消耗会越来越大。
所以应当及时释放对对象的引用,让GC能够回收这些内存控件。
对象:
obj=null
对象属性:
deleteobj.myproperty
数组item:
使用数组的splice方法释放数组中不用的item
2.5避免string的隐式装箱
说明:
对string的方法调用,比如'xxx'.length,浏览器会进行一个隐式的装箱操作,将字符串先转换成一个String对象。
推荐对声明有可能使用String实例方法的字符串时,采用如下写法:
varmyString=newString('HelloWorld');