JavaScript提供了20多个命令,分别执行不同的操作。从用途分析,这些命令可以分为:声明语句、分支控制、循环控制、流程控制、异常处理和其他语句。本贴将重点讲解程序结构设计命令,包括if条件判断语句、switch多分支语句、for循环语句、while循环语句、do/while循环语句、break中断语句、continue继续执行语句等。
1、分支结构
1.1、if语句
if语句允许根据特定的条件执行指定的语句,语法格式如下:
if (expr)
statement
如果表达式expr的值为真,则执行语句statement;否则,将忽略语句statement。
【示例】使用内置函数Math.random()随机生成一个1~100的整数,然后判断该整数能否被2整除,如果可以整除,则输出显示:
var num = parseInt( Math.random()*99 + 1 ); //使用random()函数生成一个随机数
if ( num % 2 == 0){ //判断变量num是否为偶数
console.log( num + "是偶数。");
}
提示:如果statement为单句,可以省略大括号,例如:
if ( num % 2 == 0)
console.log( num + "是偶数。");
1.2、else语句
else语句仅在if或elseif语句的条件表达式为假的时候执行,语法格式如下:
if (expr)
statement1
else
statement2
如果表达式expr的值为真,则执行语句statement1;否则,将执行语句statement2。其流程控制如下图所示:
var num = parseInt( Math.random()*99 + 1 ); //使用random()函数生成一个随机数
if ( num % 2 == 0){ //判断变量num是否为偶数
console.log( num + "是偶数。");
} else {
console.log( num + "是奇数。");
}
1.3、switch语句
switch语句专门用来设计多分支条件结构。与if else多分支结构相比,switch结构更简洁,执行效率更高。语法格式如下:
switch (expr){
case value1:
statementList1
break;
case value2:
statementList2
break;
…
case valuen:
statementListn
break;
default:
default statementList
}
switch语句根据表达式expr的值,依次与case后面表达式的值进行比较。如果相等,则执行其后的语句段,只有遇到break语句或者switch语句结束才终止;如果不相等,继续查找下一个case。switch语句包含一个可选的default语句,如果在前面的case中没有找到相等的条件,则执行default语句,它与else语句类似。switch语句流程控制如下图所示:
1.4、default语句
default是switch的子句,可以位于switch内的任意位置,不会影响多重分支的正常执行。下面结合示例介绍使用default语句应该注意的3个问题。
提示:如果default下面还有case子句,应该在default后面添加break语句,终止switch结构,防止程序突破case条件的限制继续执行下面的case子句。
【示例】使用switch语句设计一个四则运算函数。在switch结构内,先使用case枚举4种可预知的算术运算,当然还可以继续扩展case子句,枚举所有可能的操作,但是无法枚举所有不测,因此最后使用default处理意外情况。
提示:default语句与case语句简单比较如下:
- 语义:default为默认项,case为判例。
- 功能扩展:default选项是唯一的,不可以扩展;而case选项是可以扩展的,没有限制。
- 异常处理:default与case扮演的角色不同,case用于枚举,default用于异常处理。
2、循环结构
2.1、while语句
while语句是最基本的循环结构,语法格式如下:
while (expr)
statement
当表达式expr的值为真时,将执行statement语句,执行结束后,再返回到expr表达式继续进行判断。直到表达式的值为假,才跳出循环,执行下面的语句。while循环语句的流程控制如下图所示:
【示例】使用while语句输出1~100的偶数:
var n = 1; //声明并初始化循环变量
while(n <= 100){ //循环条件
n ++ ; //递增循环变量
if( n%2 == 0) document.write( n + " " ); //执行循环操作
}
2.2、do…while语句
do…while与while循环相似,区别在于表达式的值是在每次循环结束时检查,而不是在开始时检查。因此,do…while循环能够保证至少执行一次循环,而while循环就不一定了。如果表达式的值为假,则直接终止循环,不进入循环。语法格式如下:
do
statement
while (expr)
do…while循环语句的流程控制如下图所示:
提示:建议在do…while结构的尾部使用分号表示语句结束,以避免意外情况发生。
2.3、for语句
for语句的结构是一种更简洁的循环结构,语法格式如下:
for (expr1; expr2; expr3)
statement
其中,表达式expr1在循环开始前无条件地求值一次,而表达式expr2在每次循环开始前求值。如果表达式expr2的值为真,则执行循环语句,否则将终止循环,执行下面代码。表达式expr3在每次循环之后被求值。for循环语句的流程控制如下图所示:
【示例】使用嵌套循环求1~100的所有素数。外层for循环遍历每个数字,在内层for循环中,使用当前数字与其前面的数字求余。如果有至少一个能够被整除,则说明它不是素数;如果没有一个被整除,则说明它是素数,最后输出当前数字:
for(var i=2 ; i<100 ; i++){//打印2~100的素数
var b = true;
for(var j = 2; j < i; j++){
//判断i能否被j整除,能被整除则说明不是素数,修改布尔值为false
if(i%j == 0) b = false ;
}
if(b) document.writeln(i + " "); //打印素数
}
2.4、for…in语句
for…in语句是for语句的一种特殊形式,语法格式如下:
for ( [var] variable in <object | array> )
statement
variable表示一个变量,可以在其前面附加var语句,用来直接声明变量名。in后面是一个对象或数组类型的表达式。在遍历对象或数组过程中,把获取的每一个值赋值给variable。
然后,执行statement语句,其中可以访问variable读取每个对象属性或数组元素的值。执行完毕,返回继续枚举下一个元素,周而复始,直到所有元素都被枚举为止。
注意:对于数组来说,值是数组元素的下标;对于对象来说,值是对象的属性名或方法名。
【示例1】使用for…in语句遍历数组,并枚举每个元素及其值:
var a = [1, true, "0", [false], {}]; //声明并初始化数组变量
for(var n in a){ //遍历数组
document.write( "a[" + n + "] = " + a[n] + "<br>" ); //显示每个元素及其值
}
3、流程控制
3.1、label语句
在JavaScript中,使用label语句可以为一行语句添加标签,以便在复杂结构中设置跳转目标。语法格式如下:
label : statements
label为任意合法的标识符,但不能使用保留字。使用冒号分隔标签名与标签语句。
注意:由于标签名与变量名属于不同的命名体系,所以标签名与变量名可以重复。但是,标签名与属性名语法相似就不能重名。例如,下面写法是错误的:
a:{ //标签名
a:true //属性名
}
使用点语法、中括号语法可以访问属性,但是无法访问标签语句:
console.log(o.a); //可以访问属性
console.log(b.a); //不能访问标签语句,将抛出异常
label与break语句配合使用,主要应用在循环结构、多分支结构中,以便跳出内层嵌套体。
3.2、break语句
break语句能够结束当前for、for/in、while、do/while或者switch语句的执行。同时,break语句可以接收一个可选的标签名决定跳出的结构语句。语法格式如下:
break label;
如果没有设置标签名,则表示跳出当前最内层结构。break语句流程控制如下图:
【示例1】在客户端查找document的bgColor属性。由于完全遍历document对象会浪费时间,因此设计一个条件,判断所枚举的属性名是否等于bgColor。如果相等,则使用break语句跳出循环:
for(i in document){
if(i.toString() == "bgColor"){
document.write("document." + i + "=" + document[i] +
"<br />");
break;
}
}
在上面代码中,break语句并非跳出当前的if结构体,而是跳出当前最内层的循环结构。
【示例2】在嵌套结构中,break语句并没有跳出for/in结构,仅仅退出switch结构:
for(i in document){
switch(i.toString()){
case "bgColor":
document.write("document." + i + "=" + document[i] + "<br />");
break;
default:
document.write("没有找到");
}
}
【示例3】针对示例2,可以为for…in语句定义一个标签outloop,然后在最内层的break语句中设置该标签名,这样当条件满足时就可以跳出最外层的for…in循环结构:
outloop:for(i in document){
switch(i.toString()){
case "bgColor":
document.write("document." + i + "=" + document[i] + "<br />");
break outloop;
default:
document.write("没有找到");
}
}
注意:break语句和label语句配合使用仅限于嵌套的循环结构,或者嵌套的switch结构,且需要退出非当前层结构时。break与标签名之间不能够包含换行符,否则JavaScript会解析为两个句子。
break语句的主要功能是提前结束循环或多重分支,主要用在无法预控的环境下,避免死循环或者空循环。
3.3、continue语句
continue语句用在循环结构内,用于跳过本次循环中剩余的代码,并在表达式的值为真时,继续执行下一次循环。它可以接收一个可选的标签名,来决定跳出的循环语句。语法格式如下:
continue label;
4、异常处理
4.1、try/catch/finally语句
try/catch/finally是JavaScript异常处理语句,语法格式如下:
try{
//调试代码块
}
catch(e){
//捕获异常,并进行异常处理的代码块
}
finally{
//后期清理代码块
}
在正常情况下,JavaScript按顺序执行try子句中的代码。如果没有异常发生,则会忽略catch子句,跳转到finally子句中继续执行。
如果在try子句中运行时发生错误,或者使用throw语句主动抛出异常,则执行catch子句中的代码,同时传入一个参数,引用Error对象。
注意:在异常处理结构中,大括号不能够省略。
【示例1】先在try子句中制造一个语法错误,然后在catch子句中获取Error对象,读取错误信息,最后在finally子句中提示代码:
try{
1=1; //非法语句
}
catch(error){ //捕获错误
console.log(error.name); //访问错误类型
console.log(error.message); //访问错误详细信息
}
finally{ //清除处理
console.log("1=1"); //提示代码
}
catch和finally子句是可选的。在正常情况下,应该包含try和catch子句。
try{ 1=1; }
catch(error){}
注意:不管try语句是否完全执行,finally语句最后都必须执行。即使使用跳转语句跳出了异常处理结构,也必须在跳出之前先执行finally子句。
【示例2】在函数体内设计一个异常处理结构,为每个子句添加一个return语句。调用函数后,实际返回的是“finally”,而不是“try”,因为finally子句必须最后执行。如果把finally子句去掉,函数才会返回“try”:
function test(){
try{
return "try";
}catch(error){
return "catch";
}finally{
return "finally";
}
}
console.log( test()); //返回"finally"
try/catch/finally语句允许嵌套使用,嵌套的层数不限,同时形成一条词法作用域链。在try中发生异常时,JavaScript会停止程序的正常执行,并跳转到层级最近的catch子句(异常处理器)。如果没有找到异常处理器,则会沿着作用域链,检查上一级的catch子句,以此类推,直到找到一个异常处理器为止。如果在程序中没有找到任何异常处理器,将会显示错误。
4.2、throw语句
throw语句能够主动抛出一个异常,语法格式如下:
throw expression;
expression是任意类型的表达式,一般为Error对象,或者Error子类实例。
当执行throw语句时,程序会立即停止执行。只有当使用try/catch语句捕获到被抛出的值时,程序才会继续执行。
【示例】在循环体内设计当循环变量大于5时,定义并抛出一个异常:
try{
for(var i=0; i<10;i++){
if(i>5) throw new Error("循环变量的值大于5了"); //定义错误对象,并抛出异常
console.log(i);
}
}
catch(error){ } // 捕获错误,其中error就是new Error()的实例
在抛出异常时,JavaScript也会停止程序的正常执行,并跳转到最近的catch子句。如果没有找到catch子句,则会检查上一级的catch子句,以此类推,直到找到一个异常处理器为止。如果在程序中没有找到任何异常处理器,将会显示错误。