JS中的while和for循环该如何选择?

for 和 while 语句都可以完成特定动作的重复性操作。不过,使用时不可随意替换。简单比较如下。

语义

for 语句是以变量的变化来控制循环进程的,整个循环流程是计划好的,可以事先知道循环的次数、每次循环的状态等信息。

while 语句是根据特定条件来决定循环进程的,这个条件时动态的,无法预知的,存在不确定性,每一次循环时都不知道下一次循环的状态如何,只能通过条件的动态变化来确定。

因此,for 语句常用于有规律的重复操作中,如数组、对象等迭代。while 语句更适用于特定条件的重复操作,以及依据特定事件控制的循环操作。

模式

在 for 语句中,把循环的三要素(起始值、终止值和步长)定义为 3 个基本表达式,作为结构语法的一部分固定在 for 语句内,使用小括号进行语法分隔,这与 while 语句内条件表达式截然不同,这样更有利于 JavaScript 解释器进行快速编译。

for 语句适合简单的数值迭代操作。

示例1

下面代码使用 for 语句迭代 10 之内的正整数。
for (var n = 1;n < 10;n ++) {  //循环操作的环境条件
    console.log(n);  //循环操作的语句
}
用户可以按以下方式对 for 循环进行总结。
  • 执行循环条件:1<n<10,步长为 n++。
  • 执行循环语句:console.log(n);

这种把循环操作的环境条件和循环操作语句分离开的设计模式能够提高程序的执行效率,同时也避免了把循环条件与循环语句混在一起而造成的贻误。如果使用简化的示意图来描述这种思维模式则如图所示。


如果循环结构比较复杂,for 语句就必须考虑如何把循环条件和循环语句联系起来才可以正确执行整个 for 结构。因为根据 for 结构的运算顺序,for 语句首先计算第一、二个表达式,然后执行循环体语句,最后返回执行 for 语句第三个表达式,如此周而复始。

示例2

下面代码使用 for 语句模拟 while 语句在循环体内的检测条件,并根据递增变量的值是否小于 10。如果大于等于 10,则设置条件变量 a 的值为 false,终止循环。
for (var a = true,b = 1,a;b ++) {
    if (b > 9)  //在循环体内间接计算迭代的步长
    a = false;
    console.log(b);
}
在上面示例中,for 语句的第三个表达式不是直接计算步长的,整个 for 结构也没有明确告知循环步长的表达式,要确知迭代的步长就必须根据循环体内的语句来决定。于是整个 for 结构的逻辑思维就存在一个循环的过程,如图所示。


由于 for 结构的特殊性,导致在执行复杂条件时会大大降低效率。相对而言,while 结构天生就是为复杂的条件而设计的,它将复杂的循环控制放在循环体内执行,而 while 语句自身仅用于检测循环条件,这样就避免了结构分离和逻辑跳跃。

示例3

下面代码使用 while 语句迭代 10 之内的正整数。如果使用示意图来勾勒这种思维变化,则如下图所示。
var a = true,b = 1;
while (a) {
    if (b > 9) {
    a = false;  //在循环体内间接计算迭代
    console.log(b);
    b ++;  //在循环体内间接计算迭代
}

目标

有些循环次数在循环之前就可以预测,如计算 1~100 之间的数字和;而有些循环则具有不可预测性,用户无法事先确定循环的次数,甚至无法预知循环操作的趋向。这些都构成了在设计循环结构时必须考虑的达成目标问题。

即使是相同的操作,如果达成目标的角度不同,可能重复操作的设计也不同。例如,统计全班学生的成绩和统计合格学生的成绩就是两个不同的达成目标。

一般来说,在循环结构中动态改变循环变量的值时,建议使用 while 结构,而对于静态的循环变量,则可以考虑使用 for 结构。简单比较 while 和 for 语句,区别如表所示。

while 语句和 for 语句的比较
语句 while 语句 for 语句
条件 根据条件表达式的值决定循环操作 根据操作次数决定循环操作
结构 比较复杂,结构相对宽松 比较简洁,要求比较严格
效率 存在一定的安全隐患 执行效率比较高
变种 do/while 语句 for/in 语句