也谈JavaScript代码性能优化
差不多两年前写了个选择器whiz,除在DOM查找方面做了许多优化工作之外,还在代码优化上做了很多工作,一直没有分享。抽空总结一下,基本上在jQuery、Mootools和YUI的源码里面都可以看到这些写法。有些是已经在网上分享很多遍了,众所周知的,也有一些可能写了多年的JavaScript的开发人员也不一定想得到的。如果有说得不正确的地方,还请大家指出。还有特别说明的是,其中某些写法不是很推荐,虽然代码简洁了,但是有可能造成阅读困难。
1.尽量使用源生方法(Native Method)
js是解释性语言,相比编译性语言执行速度要慢。如果浏览器已经实现了该方法,就不要再用js再去实现一遍了。另外,绝大部分情况下,浏览器已经实现的方法已经在算法方面做了很多优化,再重复实现一遍只是浪费时间和精力还有带宽。当然,如果你只是为了练习算法,那另当别论。
2.尽可能减少循环次数
代码的瓶颈大多在循环,少一层循环,就能数倍地提高性能。如果要对一个数组的每个元素进行多次操作,尽可能使用一次循环,多次操作,而不是多次循环,每次循环执行一次操作。尤其是在进行多个正则匹配的时候,尽可能合并正则表达式,在一次遍历中尽可能找到相应的匹配。
3.循环的另外一种写法
通常循环的写法:
var objs = [obj1, obj2, obj3], i = 0; len = objs.length;
for(i = 0; i < len; i++){
dosth(obj);
}
当循环遍历的对象是object时,可以采用下面的方式来写:
var objs = [obj1, obj2, obj3], obj, i = 0;
while(obj = objs[i++]){
dosth(obj);
}
特别注意,如果你的数组里面有可能出现0, false, null等等在条件判断为false的值,这种写法是不正确的。
4.某些情况下switch的另外一种写法
通常的switch写法:
function fun_a(){}
function fun_b(){}
function fun_c(){}
switch(con){
case 'a':
fun_a();
break;
case 'b':
fun_b();
break;
case 'c':
fun_c();
break;
}
另外一种写法:
function fun_a(){}
function fun_b(){}
function fun_c(){}
var funs = {
'a': fun_a,
'b': fun_b,
'c': fun_c
};
funs[con]();
取值或者函数调用都可以用类似的方式来做。
5.条件判断的另外一种写法
通常情况下:
if(a){
dosth();
}
可以这样写:
a && dosth();
6.创建对象的另外一个办法,不使用new
很多时候,我们要连续创建一些简单的object对象,并且拥有默认的属性,很多人会这么写:
function Klass(){
this.prop_a = '';
this.prop_b = [];
this.prop_c = 0;
}
var objs = [], i = 0, obj;
while(i<100){
obj = new Klass();
obj.prop_c = i;
objs.push(obj);
}
换种写法看看:
function create(){
return {
prop_a : '',
prop_b : [],
prop_c : 0
};
}
var objs = [], i = 0, obj;
while(i<100){
obj = create();
obj.prop_c = i;
objs.push(obj);
}
当然还有直接声明的方式,但是复用性会差一些。
7.用来做标记的变量尽可能使用布尔类型
直接用true和false做标记,不要使用数字或者字符串的1和0来做标记,直接也高效。
其他的优化方法已经有很多分享了,大家可以Google一下,另外《javascript高级程序设计》一书中也对JavaScript性能优化做了较为详细的阐述。