高性能JavaScript循环语句和条件语句
本文深入分析JavaScript中循环与条件语句的性能差异。针对循环,探讨倒序迭代对for、while及do-while的提升效果,并对比for-in与forEach的开销。针对条件判断,解析if-else、switch-case及查找表的适用场景,通过二叉树查找与分支表机制提供优化策略,帮助开发者在极端性能需求与代码可读性之间做出权衡。
循环语句性能分析
一、循环语句 常见的循环结构包括for、while、do-while、for-in以及forEach。除了for-in和forEach的性能相对较低外,开发者在前三者之间的选择通常基于具体需求而非性能考量。本文将通过测试对比它们各自的性能表现,探讨在极端性能要求下可行的优化手段。
首先分析为何for-in和forEach的执行速度较慢。for-in主要用于遍历对象属性,由于每次迭代需同时搜索实例自身属性及原型链上的属性,导致效率较低。而forEach基于函数迭代(需注意所有IE版本均不支持,若需兼容可使用jQuery等库),其性能瓶颈主要源于对每个数组项调用外部方法所产生的额外开销。
接下来考察每次迭代中for、while及do-while循环的具体执行过程。
var length = items.length;
for(var i = 0; i < length; i++)
process(items[i]);
var j = 0;
while(j < length)
process(items[j++]);
var k = 0;
do {
process(items[k++]);
} while(k < length);
在上述每种循环结构中,每次执行循环体时均会执行以下操作:
- 一次控制条件中的数值大小比较(i < length)
- 一次判断控制条件结果是否为true的比较(i < length === true)
- 一次自增操作(i++)
- 一次数组元素查找(items[i])
- 一次函数调用process(items[i])
通过调整数组遍历顺序,可以提升循环性能:
for(var i = items.length; i--; )
process(items[i]);
var j = items.length;
while(j--)
process(items[j]);
var k = items.length - 1;
do {
process(items[k]);
} while(k--);
本例采用倒序循环,并将减法操作整合至循环条件中。此时,控制条件仅与0进行比较。由于任何非零数在布尔上下文中自动转换为true,而零值等同于false,控制条件的比较次数从两次(判断迭代数是否少于总数?是否为true?)减少为一次(是否为true?)。每次迭代的比较次数由两次降至一次,从而进一步提升了循环速度。
性能测试:
实际情况是否如此?通过浏览器验证可知。测试代码较为简单,针对8种不同情况封装了8个函数(在Firefox下若不添加定时器则无法打印profiles信息,具体原因不明):
// init array
var a = [];
var length = 10;
for(var i = 0; i < length; i++)
a[i] = 1;
function for_in() {
var sum = 0;
for(var i in a)
sum += a[i];
}
function for_each() {
var sum = 0;
a.forEach(function(value, index, array) {
sum += value;
});
}
function for_normal() {
var sum = 0;
for(var i = 0; i < length; i++)
sum += a[i];
}
function for_reverse() {
var sum = 0;
for(var i = length; i--; )
sum += a[i];
}
function while_normal() {
var sum = 0;
var i = 0;
while(i < length)
sum += a[i++];
}
function while_reverse() {
var sum = 0;
var i = length;
while(i--)
sum += a[i];
}
function do_while_normal() {
var sum = 0;
var i = 0;
do {
sum += a[i++];
} while(i < length);
}
function do_while_reverse() {
var sum = 0;
var i = length - 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.profileEnd();
}, 1000);
当数组长度为100时,Firefox下的结果与预期相符:for-each和for-in效率较低,倒序遍历比正序遍历效率略有提升(Chrome下的profiles因耗时过短而未显示)。
当数据量达到100万时,Firefox和Chrome下的结果均符合预期,但存在细微差异。在Firefox中,for-in的表现优于for-each;而在Chrome中,for-in表现较差并直接发出警告。尽管倒序迭代性能略有提升,但提升幅度有限,且降低了代码的可读性。


小结:
- 倒序迭代确实能略微提升代码性能,但牺牲了代码可读性。除非追求极致的性能优化,否则不建议使用。
- 遍历数组时,若可使用普通循环,应避免使用for-in和for-each。
条件语句优化策略
二、条件语句 常见的条件语句包括if-else和switch-case。那么,何时使用if-else,何时使用switch-case呢?
首先看一个简单的if-else语句代码:
if (value == 0){
return result0;
} else if (value == 1){
return result1;
} else if (value == 2){
return result2;
} else if (value == 3){
return result3;
} else if (value == 4){
return result4;
} else if (value == 5){
return result5;
} else if (value == 6){
return result6;
} else if (value == 7){
return result7;
} else if (value == 8){
return result8;
} else if (value == 9){
return result9;
} else {
return result10;
}
在最坏情况下(value=10),可能需要执行10次判断才能返回正确结果。如何优化这段代码?一个显而易见的策略是将最可能的取值提前判断,例如假设value最可能等于5或10,则将这两条判断前置。然而,通常我们并不知晓“最可能的选择”,此时可采取二叉树查找策略进行性能优化。
if (value < 6){
if (value < 3){
if (value == 0){
return result0;
} else if (value == 1){
return result1;
} else {
return result2;
}
} else {
if (value == 3){
return result3;
} else if (value == 4){
return result4;
} else {
return result5;
}
}
} else {
if (value < 8){
if (value == 6){
return result6;
} else {
return result7;
}
} else {
if (value == 8){
return result8;
} else if (value == 9){
return result9;
} else {
return result10;
}
}
}
经过上述优化,最多仅需进行4次判断即可,显著提高了代码性能。这种优化思路类似于二分查找,与二分查找相似之处在于,只有当value值为连续数字时才能进行此类优化。然而,这种写法不利于维护,若需增加一个或多个条件,则需重写大量代码。此时,switch-case语句便显示出其优势。
使用switch-case语句重写上述代码:
switch(value){
case 0:
return result0;
case 1:
return result1;
case 2:
return result2;
case 3:
return result3;
case 4:
return result4;
case 5:
return result5;
case 6:
return result6;
case 7:
return result7;
case 8:
return result8;
case 9:
return result9;
default:
return result10;
}
switch-case语句使代码更具可读性。此外,若多个value值返回相同结果,无需重复编写return部分的代码。一般而言,当case数量达到一定规模时,switch-case的执行效率高于if-else,因为switch-case采用了branch table(分支表)索引进行优化,尽管各浏览器的优化程度存在差异。
除if-else和switch-case外,还可采用查找表。
var results = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10];
//return the correct result
return results[value];
当数据量较大时,查找表的效率通常高于if-else和switch-case。查找表支持以数字或字符串作为索引;若使用字符串,建议用对象代替数组。当然,查找表的使用存在局限性:每个case对应的结果只能是一个取值,而不能是一系列操作。
小结:
- 当仅有2个case,或case的value取值是一段连续数字时,可选择if-else语句。
- 当有3至10个case,且case的value取值非线性时,可选择switch-case语句。
- 当case数量超过10个,且每次结果仅为一个取值而非额外的JavaScript语句时,可选择查找表。
以上就是本文的全部内容,希望对大家的学习有所帮助。
crypto-js 处理 Base64 和 Hex 编码转换的正确姿势
2026-11-05 16:39:11
ammo.js 内存管理:避免 Wasm 环境下的内存泄漏技巧
2026-11-05 10:21:09
JS几种补零方法的性能对比与选择建议
2026-11-04 21:17:50
JS数组去重最佳实践:Set、filter与reduce实现方案
2026-11-04 10:57:15
基准元素选择策略对 JavaScript 快速排序性能的影响
2026-11-03 22:37:29
