宝哥软件园

高性能JavaScript循环语句和条件语句

编辑:宝哥软件园 来源:互联网 时间:2021-09-18

1.循环语句众所周知,常用的循环语句有for、while、do-while和for-in、forEach。除了for-in和forEach的性能稍低之外,我们通常基于需求而不是性能考虑来选择前三个。今天,我们将测试它们各自的性能,并告诉我们在最极端的条件下还可以进行哪些优化。

首先,我们来谈谈为什么for-in和forEach比其他方法慢。For-in通常用于遍历对象的属性名。因为每次迭代都会同时搜索实例本身的属性和原型链上的属性,效率肯定是低的。ForEach是基于函数的迭代(需要注意的是,ie的所有版本都不支持它,必要时可以使用JQuery等库)。为每个数组项调用外部方法导致的开销是速度慢的主要原因。

然后让我们看看在每次迭代中,while和do-while做了什么。

var长度=items.lengthfor(var I=0;一、长度;I)流程(项目[I]);var j=0;而(j长度)过程(项目[j]);var k=0;do { process(items[k]);} while(k长度);在上述每个循环中,每次运行循环体时,都会发生这样的操作:

控制条件中数值的比较(i length),控制条件结果是否为真的比较(i length===true),自增操作(I),数组搜索(items[i]),函数调用过程(items[i])我们可以通过颠倒数组的顺序来提高循环性能:

for(var I=items . length;I-;)流程(项目[I]);var j=items.lengthwhile(j -)流程(项目[j]);var k=items . length-1;do { process(items[k]);} while(k-);在此示例中,使用了反向循环,并且在循环条件中集成了减法运算。现在每个控制条件都简单地与0进行比较。当条件与真值比较时,任何非零数字都会自动转换为真,零值等于假。事实上,控制条件是从两次比较开始的(迭代次数是否小于总数?是真的吗?)来对比一下(是真的吗?)。每次迭代从两次比较减少到一次,这进一步提高了循环速度。

性能测试:

那么真的是这样吗?金不怕浏览器测试。测试代码非常简单,针对8种不同情况封装了8个函数(由于未知原因,firefox中没有计时器无法打印配置文件信息):

//init array var a=[];可变长度=10;for(var I=0;一、长度;I)a[I]=1;函数for _ in(){ var sum=0;for(var I in a)sum=a[I];}函数for _ each(){ var sum=0;a.forEach(函数(值、索引、数组){ sum=value});} function for _ normal(){ var sum=0;for(var I=0;一、长度;I)sum=a[I];}函数for _ reverse(){ var sum=0;for(var i=长度;I-;)sum=a[I];}函数while _ normal(){ var sum=0;var I=0;而(I长度)总和=a[I];}函数while _ reverse(){ var sum=0;var i=长度;而(I-)sum=a[I];}函数do _ while _ normal(){ var sum=0;var I=0;do { sum=a[I];} while(i长度);}函数do _ while _ reverse(){ var sum=0;var i=长度-1;do { sum=a[I];} while(I-);} setTimeout(function(){ console . profile();for _ in();for _ each();for _ normal();for _ reverse();while _ normal();while _ reverse();do _ while _ normal();do _ while _ reverse();console . profile end();}, 1000);当数组长度为100时,我们发现firefox下的结果确实和预期的差不多:for-each和for-in效率低,逆序效率略高于正序。(chrome下的配置文件不会显示,因为时间太短。)

当数据量达到100w时,火狐和chrome下的结果如预期,但略有不同。ff下的For-in性能优于for-one,而chrome下的for-in性能很差,这直接给出了警告。虽然反向迭代的性能略有提高,但改善不大,降低了代码的可读性。

总结:

反向迭代可以稍微提高代码性能,但是牺牲了代码的可读性。除非追求极致的性能优化,否则无需遍历阵列。如果可以使用普通循环,就不应该使用for-in和for-each Conditional语句常见的条件语句包括if-else和switch-case,那么什么时候应该使用if-else和switch-case语句呢?

让我们首先来看一个简单的if-else语句的代码:

if(value==0){ return result 0;} else if(value==1){ return result 1;} else if(value==2){ return result 2;} else if(value==3){ return result 3;} else if(value==4){ return result 4;} else if(value==5){ return result 5;} else if(value==6){ return result 6;} else if(value==7){ return result 7;} else if(value==8){ return result 8;} else if(value==9){ return result 9;} else { return result10}在最坏的情况下(value=10),我们可能要做10个判断才能返回正确的结果,那么如何优化这段代码呢?一个明显的优化策略是提前判断最可能的值。例如,如果该值最有可能等于5或10,则这两个判断将提前。但是通常我们不知道(最有可能的选择),所以我们可以采用二叉树搜索策略来优化性能。

if(值6){ if(值3){ if(值==0){ return result 0;} else if(value==1){ return result 1;} else {返回结果2;} } else { if(value==3){ return result 3;} else if(value==4){ return result 4;} else { return result5} }} else { if(值8){ if(值==6){ return result 6;} else {返回结果7;} } else { if(value==8){ return result 8;} else if(value==9){ return result 9;} else { return result10}}}经过这次优化,我们最多可以做出4个判断,大大提升了代码的性能。这种优化思路有点类似于二分搜索法。与二分搜索法类似,该优化只能在值为连续数时执行。但是,如果用这种方式编写代码,不利于维护。如果您想添加一个条件或多个条件,您将不得不重写大量代码,然后switch-case语句将会很有用。

用switch-case语句重写上面的代码:

switch(value){ case 0:返回结果0;案例1:返回结果1;案例2:返回结果2;案例3:返回结果3;案例4:返回结果4;案例5:返回结果5;案例6:返回结果6;案例7:返回结果7;案例8:返回结果8;案例9:返回结果9;default:返回结果10;}swtich-case语句使代码可读性更强,swtich-case语句还有一个优点,就是如果多个value值返回相同的结果,就不需要重写代码的返回部分。一般来说,当案例数量达到一定数量时,swtich-case语句的效率要高于if-else,因为switch-case是利用分支表索引进行优化的,当然优化的程度因浏览器而异。

除了if-else和swtich-case,我们还可以使用查找表。

var结果=[结果0、结果1、结果2、结果3、结果4、结果5、结果6、结果7、结果8、结果9、结果10];//返回正确的结果返回结果[值];当数据量较大时,查找表的效率通常高于if-else语句和swtich-case语句。查找表可以使用数字和字符串作为索引。如果是字符串,最好用对象代替数组。当然,查找表的使用是有限的,每种情况对应的结果只能是一个值,而不是一系列的运算。

总结:

当只有两个事例或者事例的值是连续数时,我们可以选择if-else语句。当有3~10个案例且案例的值为非线性时,可以选择switch-case语句。当案例数达到10个以上,每个案例的结果只有一个值而不是额外的JavaScript语句时,我们可以选择查找表。以上就是本文的全部内容,希望对大家的学习有所帮助。

更多资讯
游戏推荐
更多+