《JavaScript和jQuery实战手册(原书第2版)》——3.3节使用循环处理重复性任务

3.3 使用循环处理重复性任务
有时候,脚本需要一次又一次地重复同样的一系列步骤。例如,假设有一个Web表单,它带有30个文本字段。当用户提交该表单的时候,我们想要确保没有一个字段为空。换句话说,你需要执行同样的一组操作30次,即检查一个表单字段是否为空。既然计算机善于执行重复性的任务,JavaScript包含快速地重复做同样事情的工具就有意义了。
用编程术语来说,重复执行同样的任务叫做循环,由于循环在编程中如此常见,因此JavaScript提供了几种类型的循环。它们都做同样的事情,只不过方式略有不同。

3.3.1 while循环
用while循环重复一段代码,只要一个特定的条件为true;换句话说,只要条件为true。while循环的基本结构如下:

while (condition) {
 // javascript to repeat
}

第一行代码引入了while循环。和条件语句一样,我们把条件放置在紧跟while之后的一对圆括号中。条件是可以在条件语句中使用的任何测试,例如x > 10或answer == 'yes'。就像条件语句一样,如果条件为true,JavaScript解释器运行开始花括号和结束花括号之间的所有代码。
然而,和条件语句不同,当JavaScript解释器遇到了while语句的结束花括号,它会跳回到while语句的顶部并再次测试条件,而不是继续程序的下一行。如果条件再次为true,解释器再次运行花括号之间的JavaScript代码。这个过程持续到条件不再为true时为止,然后,程序继续循环之后的下一条语句(参见图3-5)。


《JavaScript和jQuery实战手册(原书第2版)》——3.3节使用循环处理重复性任务

假设想要在页面上显示数值1~5。做到这一点的一种可能的方式是:

document.write('Number 1 <br>');
document.write('Number 2 <br>');
document.write('Number 3 <br>');
document.write('Number 4 <br>');
document.write('Number 5 <br>');
注意,每行代码都几乎相同:每行之间只有数值不同。在这种情况下,循环提供了一种更高效的方式来实现同样的目标:
var num = 1;
while (num <= 5) {
 document.write('Number ' + num + '<br>');
 num += 1;
}

代码的第一行var num = 1不是while循环的一部分:它设置了一个变量来存储要在页面上显示的数值。第二行代码是循环的开始。它设置了测试条件。只要存储在变量num中的数值小于或等于5,花括号之间的代码就会运行。当第一次遇到测试条件,num的值是1,因此测试为true(1小于5),并且document.write()命令执行,‘Number 1< br>’显示到页面(
只是一个HTML分行,确保每一行在Web页面上显示为单独一行)。
提示: 编写num = num +1的一种更加紧凑的方式(这只是给存储在num变量中的当前值增加1)如下所示:

    num++
这种简写的方法也为变量num加1(参见表2-3了解详细信息)。

循环的最后一行num = num + 1非常重要。它不仅把num的值增加到1,以便能够显示下一个数值(例如,2),而且它使得测试条件最终可能变为false(如果觉得+=这样的东西看上去很奇怪,那么,可以回到本书2.5.5节,了解一下它是如何工作的)。只要条件是true,while循环中的JavaScript代码就会重复,因此,我们必须改变条件的一个要素以便条件最终变为false,从而停止循环并转向脚本的下一部分。如果测试条件不会变为false,最终将得到一个所谓的无限循环,即不会终止的程序。注意,如果在循环中漏掉了这一行,将会发生什么:

var num = 1;
while (num <= 5) { // this is an endless loop
 document.write('Number ' + num + '<br>');
}

第一次迭代这个循环,测试会询问:1小于等于5吗?答案是肯定的,因此document.write()运行。在循环的末尾(最后一个花括号),JavaScript解释器回到了循环的开始处并再次测试条件。此时,num仍然是1,因此,条件再次为真,并且再次执行document.write()。又一次,JavaScript解释器回到了循环的开始处并第三次测试条件。我们可以看看会发生什么情况:无数多行都显示“Number 1”。
这个简单的例子还展示了循环所提供的一些灵活性。例如,假设想要显示的数值是1~100,而不是1~5。只需要更改测试条件,而不是加入更多的document.write()命令的代码行,如下所示:

var num = 1;
while (num <= 100) {
 document.write('Number ' + num + '<br>');
 num = num + 1;
}

现在,循环将会执行100次,向页面显示100行。
3.3.2 循环和数组
当处理一种常见的JavaScript元素(数组)的时候,你会发现循环有了用武之地。还记得2.8节介绍过,数组是数据的一个集合。我们可以把数组看做一种购物清单。当我们要去购物的时候,实际上是执行一种循环:在商店寻找清单上的一件商品,找到之后,将它放入购物车;然后继续寻找清单上的下一件商品,再放入购物车,以此类推;直到已经遍历完整个清单。然后就结束了(这就像是退出循环),并且去收银台结账(换句话说,继续程序的下一个步骤)。
在JavaScript中,可以使用循环来遍历数组中的项目并且在每个项目上执行一项任务。例如,假设我们要构建一个程序来生成日历。这个日历完全是使用JavaScript生成的,并且我们想要在日历上显示每一天是星期几。我们可能首先把星期几的名字存储到一个数组中,如下所示:

var days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', ?
      'Friday', 'Saturday', 'Sunday'];

注意: 上面代码中的8表示JavaScript代码的这些行属于单独的一行。由于本书页面的宽度有限,有时候一行代码无法在单独一行文字中显示,因此本书使用8符号来表示应该出现在单独一行中的代码。如果你打算把这些代码输入到文本编辑器中,就要把它们作为长长的一行输入(并且省略掉8)。
现在遍历数组中的每个项目并在页面中显示。别忘了使用项目的索引值来访问数组中的一项。例如,上面的days数组的第一项(Monday),通过days[0]来访问。第二项是days[1],以此类推。
下面展示如何使用一个while循环来显示这个数组中的每一项:

var counter = 0;
while (counter < days.length) {
  document.write(days[counter] + ', ');
  counter++;
}

第一行var counter = 0设置(或者用程序员的话来说,叫做初始化)一个counter变量,它用作测试条件的一部分,也用作访问数组项目的索引。条件counter < days.length只是询问counter中存储的当前值是否小于数组的项数(别忘了,在2.8.2节介绍过,数组中项目的总数存储在数组的length属性中)。在这个例子中,该条件检查counter是否小于7(一个星期中的天数)。如果counter小于7,那么循环开始,星期几就会显示到页面上(后面跟着一个逗号和一个点号),并且,counter增加1(counter++和counter = counter + 1是相同的,参见3.3.1节的“提示”部分)。在循环运行之后,再次尝试测试;循环继续运行,直到测试结果为false。这个过程如图3-6表示。


《JavaScript和jQuery实战手册(原书第2版)》——3.3节使用循环处理重复性任务

3.3.3 for循环
JavaScript还提供了另一种类型的循环,叫做for循环,这是一种更加紧凑的形式(而且更容易令人混淆)。for循环通常用来重复一系列的步骤一定的次数,因此,它们通常包含某种类型的计数器变量、一个条件测试以及改变计数器变量的一种方法。在很多情况下,for循环可以实现和while循环相同的事情,而只需要寥寥数行代码。例如,下面是3.3.1节中的while循环:

var num = 1;
while (num <= 100) {
 document.write('Number ' + num + '<br>');
 num += 1;
}
可以使用一个for循环实现同样的效果,而只需要3行代码:
for (var num=1; num<=100; num++) {
 document.write('Number ' + num + '<br>');
}

刚一开始,for循环可能看上去有点容易令人混淆,但是,一旦搞清楚了for语句的不同部分,它们就没那么难了。每个for循环以关键字for开始,后面跟着一对圆括号和一对花括号,圆括号中包含了3个部分。和while循环一样,花括号中的内容(在这个例子中是document.write('Number ' + num + '
');)就是作为循环的一部分而执行的JavaScript代码。
表3-2说明了圆括号中的3个部分,但是,简单地说,第一部分(var num=1;)初始化了一个计数器变量。这个步骤只是在语句刚开始运行的时候发生一次。第二部分是条件,测试该条件看看循环是否运行;第三部分是在每次循环的末尾发生的一个操作,它通常改变计数器的值,因此,测试条件最终为false并且循环结束。
表3-2:理解for循环的各个部分


《JavaScript和jQuery实战手册(原书第2版)》——3.3节使用循环处理重复性任务

由于for循环提供了一种容易的方法来重复一系列步骤一定次数,它们对于遍历数组的元素效果很理想。图3-6中的while循环把数组中的每个项都显示到页面,可以使用一个for循环重新编写它,代码如下所示:

var days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', ?
      'Friday', 'Saturday', 'Sunday'];
for (var i=0; i<days.length; i++) {
    document.write(days[i] + ', ');
}
提示:    优秀的程序员经常为for循环中的计数器变量使用一个非常简短的名字。在上面的代码中,字母i充当计数器的名字。一个字母的名字(i、j和z都很常用)很快就可以录入,并且由于这个变量除了运行循环以外不作他用,因此没必要提供一个像counter这样描述性强的名字。
到目前为止的例子都是计数到一定的次数然后停止循环,但是也可以反向计数。例如,假设我们想要按照相反的顺序来显示数组中的项目(换句话说,数组中的最后一项先显示),可以这么做:
var example = ['first','second','third','last'];
for (var j = example.length ; j > 0; j--) {
    document.write(example[j-1] + '<br>');
}

在这个例子中,计数器变量j从数组中的总数(4)开始。每循环一次,测试j中的值是否大于0;如果是,运行花括号之间的代码。然后,从j中减去1(j——),然后再次运行测试。唯一的具有技巧的部分就是程序访问数组项目的方式(example[j-1])。既然数组索引从0开始,那么数组的最后一项的索引就是数组中项目总数减去1(参见2.8.2节的介绍)。这里,j从数组中的项目的总数开始,因此,为了访问最后一项,必须从j减去1以获取正确的项目。
3.3.4 do/while循环
还有另一种不那么常见的循环类型,叫做do/while循环。这种类型的循环基本上和while循环相同,它的基本结构如下所示:

do {
 // javascript to repeat
} while (condition) ;

在这种循环中,条件测试发生在末尾,即在循环运行之后。因此,花括号中的JavaScript代码总是至少运行一次。即便条件不为true,也只有在代码运行一次之后才会进行测试。
可以使用这种循环的情况并不太多,但是,当想要提示用户输入的时候,它非常有用。我们在本章前面(3.2节中的教程)见到的教程是一个很好的例子。那段脚本要求访问者输入一个数值。它包含了一个失效预防系统,因此,如果访问者没有输入一个数值,脚本要求他们再次输入一个数值。遗憾的是,如果某人真的很顽固并且再次输入数值以外的内容,就会在页面上显示一条无意义的消息。
然而,有了do/while循环,就可以继续提示访问者输入一个数值,直到他确实输入了一个数值。为了看看如何做到这一点,我们将编辑在3.2节的教程中完成的页面:

  1. 在文本编辑器中打开在3.2节的教程中完成的页面conditional.html。
    (如果你没有完成该教程,可以直接打开文件complete_conditional.html)。我们将使用一个do/while循环来替代靠近页面顶部的代码。
  2. 找到页面的< head>部分的< script>标签之间的代码,并且删除如下粗体所示的代码:
    var luckyNumber = prompt('What is your lucky number?','');
    luckyNumber = parseInt(luckyNumber, 10);
    if (isNaN(luckyNumber)) {
     luckyNumber = prompt('Please, tell me your lucky number.','');
    }

删除的代码提供了第二个提示对话框。我们不再需要这些代码。相反,把剩下的代码包含到一个do/while循环中。

  1. 把光标放到代码的第一行(以var luckyNumber开始的一行)并输入:
    do {

这行代码创建了循环的开头。接下来将完成循环并添加测试条件。

  1. 单击这段JavaScript代码的最后一行,并且输入:} while (isNaN(luckyNumber));。完整的代码段如下所示:
    do {
     var luckyNumber = prompt('What is your lucky number?','');
     luckyNumber = parseInt(luckyNumber, 10);
    } while (isNaN(luckyNumber));

保存文件并在Web浏览器中预览。尝试在提示框中输入文本和其他的非数字符号。这个恼人的对话框持续出现,直到你真正地输入了一个数字。
它是这么工作的:do关键字告诉JavaScript解释器,让它准备进入一个do/while循环。下面的两行代码随后运行,因此,提示框出现并且将访问者的回答转换成一个整数。只有此时才进行条件测试。这和3.2节教程的脚本中的条件相同:它只是检查从访问者那里获取的输入是否“非数值”。如果输入不是一个数值,循环重复。换句话说,只要输入的是非数值,提示继续出现。这种方法的好处是,它保证了提示框至少出现一次,因此,如果访问者确实输入了一个数值作为问题的回答,就没有循环。在Chapter03文件夹的complete_do-while.html中可以看到一个完整有效的教程。

上一篇:《PHP、MySQL和Apache入门经典(第5版)》一一2.3 在Linux/UNIX上安装MySQL


下一篇:实现Runnable和继承Thread 创建多线程方法的对比