第3章:基本概念(语句)

3.6 语句

ECMAScript-262规定了一组语句(也称为流程控制语句)。从本质上看,语句定义了ECMAScript中的主要的语法,语句通常使用一个或者多个关键字来完成指定任务。语句可以很简单,例如通知函数退出;也可以比较复杂,例如指定重复执行某个命令的次数。

3.6.1 if 语句

大多数变成语言中最常用的一个语句就是if语句。以下是if语句的语法:

if(condition) statement1 else statement2

其中condition可以是任意表达式;而且对这个表达式求值结果不一定是布尔值。ECMAScript会自动调用Boolean()函数将这个表达式的结果转换为一个布尔值。如果对condition求值的结果是true,则执行statement1,如果是false,则执行statement2。而且这个语句既可以是一行代码,也可以是一个代码块。请看下面的例子:

if(i > 25)
    alert("Greater than 25.");
else{
    alert("Less than or equal to 25.");
}

不过,业界普遍推崇的最佳实践始终是是使用代码块,即使要执行的只有一行代码,因为这样可以消除人们的误解,否则可能让人分不清楚在不同条件下要执行那些语句。

另外,也可以详细面这样把整个if语句写在一行代码中。

if(condotion1) statement1 else if(condition2) statement2 else statement3;

但是我们更推崇下面这样:

if(i > 25){
    ...
}else if(i < 0){
    ...
}else{
    ...
}

3.6.2 do-while语句

do-while语句是一种后测试循环语句,即只有在循环体中的代码执行之后,才会测试出口条件。换句话说,在对表达式求值之前,循环体内的代码至少被执行一次。一下是do-while语句的语法:

do{
    statement;
}while(expression);

向do-while这种后测试循环语句嘴长用于循环体中的代码至少要被执行一次的情形。

3.6.3 while语句

while语句属于前测试循环语句,也就是说,在循环体内的代码被执行之前,就对出口条件求值。因此,循环体内的代码有可能永远不会执行。以下是while语句的语法:

while(expression) statement;

下面是一个示例:

var i = 0;
while(i<10){
i += 2;
}

在这个例子中,变量i开始时候的值为0,每次循环都会递增2。而只是i的值小于10,循环会继续下去。

3.6.4 for 语句

for语句也是一种前测试循环语句,它具有执行之前初始化变量和定义后执行的代码的能力。一下是for语句的语法:

for(initialization;expression;post-loop-expression) statement

下面是一个示例:

var count = 10;
for(var i = 0;ui<count;i++){
    alert(i);
}

以上代码定义了变量i的初始值为0。只有当表达式返回true的情况下才会进入for循环,因此也有可能不会执行循环体中的代码。如果执行了循环体中的代码,则一定对循环后的表达式i++求值,即递增i的值。这个for循环语句与下面的while语句功能相同:

var count = 10;
var i = 0;
while(i < count){
    alert(i);
    i++;
}

使用while循环做不到的,使用for循环同样也做不到。也就是说,for循环只是把循环有关的代码集中在一个位置。

有必要指出的是,在for循环的变量初始化表达式中,也可以不使用var关键字。该变量的初始化在外部执行,例如:

var count = 10;
var i;
for(i = 0;i<count;i++){
    alert(i)
}

以上代码在循环初始化表达式中声明变量的效果是一样的。由于ECMAScript中不存在块级作用域,因此在循环内部定义的变量也可以在外部访问到。例如:

var count = 10;
for(var i = 0;i<count;i++){
    alert(i);
}
alert(i);   // 10

在这个例子中,会有一个警告框显示循环完成以后变量i的值,这个只是10。这是因为,即使i是在循环内部定义的一个变量,在循环外部仍然可以访问的到它。

此外,for语句中的初始化表达式、控制表达式和循环后的表达式都是可选的。将这三个表达式全部省略,会创建一个无限循环,例如:

for(;;){
    doSomething();
}

而只给出控制表达式实际上就把for循环转换成了while循环,例如:

var count = 10;
var i = 0;
for(;i<count;){
    alert(i);
    i++;
}

由于for语句存在着极大的灵活性,因此它也是ECMAS如此平台中最常用的一个语句。

3.6.5 for-in 语句

for-in语句是一种精准的迭代语句,可以用来枚举对象的属性。以下是for-in语句的语法:

forproperty in expression) statement;

下面是一个实例:

for(var proName in window){
    document.write(proName);
}

在这个例子中,我们使用for-in循环来显示了BOM中的window对象的所有属性。每次执行循环时,都会讲window对象中存在的一个属性名赋值个变量proName。这个过程中会已知会持续到对象中的所有属性被枚举以便为止。与for语句类似,这里控制语句中的var操作符也不是必必需的。但是为了保证使用局部变量,我们推荐上面例子中的这种写法。

ECMAScript对象属性没有顺序。因此,通过for-in循环输出的属性名是不可预测的。具体来讲,所有属性都会被返回一次,凡是返回后的先后次序可能会因为浏览器而异。

但是,如果表示要迭代的变量为null或者undefined,for-in语句会抛出错误。ECMAScript5更改了这一行为;对这种情况下不再抛出错误,而只是不执行循环体。为了保证最大限度的限制兼容性,建议在使用for-in循环之前,先检测确定该对象是不是null或者undefined。

3.6.6 label语句

使用label语句可以在代码中添加标签,以便将来使用。以下是label语句的语法:

label:statement

下面是一个实例:

start:for(var i = 0;i<count;i++){
    alert(i);
}

这个例子中定义的start标签可以在将来由break或者continue语句调用。加标签的语句一般都与for语句等循环语句配合使用。

3.6.7 break和continue语句

break和continue语句用于在循环中精确地控制代码的执行。其中,break语句会立即退出循环,但是退出之后从村换的顶部继续执行。而continue语句虽然也是退出循环,但是退出循环后从循环的顶级继续执行。请看下面的例子:

var num = 0;
for(var i = 1;i<10;i++){
    if(i % 5 == 0){
        break;
    }
    num++;
}
alert(num); // 4

这个例子中的for循环会将变量i由1地增加值10。在循环体内,有一个if语句检查i的值是否可以被整除。如果是则break退出语句循环。另一方面,变量num从0开始,用于记录循环执行的次数。在执行break语句之后,要执行的下一行代码是alert()函数,结果显示是4.也就是说,在变量i等于5时,循环总共执行了4次,而break语句的执行,导致循环在num在此递增之前就退出了。如果在这里把break替换为continue的话,则可以看到另一种结果:

var num = 0;
for(var i = 1;i<10;i++){
    if(i%5 == 0){
        continue;
    }
    num++;
}
alert(num); // 8

例子的结果显示是8,也就是循环总共执行了8次。当i等于5的时,循环会在num再次递增之前退出,但是接下来的是下一次循环,即i的值等于6的循环。于是,循环又继续执行,直到i等于10自然结束。而num的最终值之所以是8,是因为continue语句导致它少递增了一次。

break和continue语句都可以与label语句关联使用,从而返回代码中特定的位置。这种联合使用的情况发生在嵌套的情况下,如下面的例子所示:

var num = 0;
outermost:
for(var i = 0;i<10;i++){
    for(var j = 0;i<10;j++){
            break outermost;
        }
        num++;
    }
}
alert(num); // 55

在这个例子中,outermost标签表示外部的for语句。如果每个循环正常执行了10次,则num++语句就会正常的执行100次。换句话说,入股如果两个循环自然结束,num的值应该是100。但是内部循环中的break语句带了一个参数:要返回的这个标签。添加这个标签的结果将导致break语句不仅会退出内部的for语句,而且也会退出外部的for语句循环。为此当变量i和j都等于5的时候,num的值当刚好是55。同样,continue语句也可以像这样与label语句联用,如下面的例子所示:

var num = 0;
outermost: 
for(var i = 0;i<10;i++){
    for(var j = 0;j<10;j++){
        if(i == 5 && j == 5){
            continue outermost;
        }
    }
}
alert(num); // 95

这种情况下,continue语句会强制执行继续执行循环–退出内部循环,执行外部循环。当j时5的时候,continue语句执行,而这意味着内部循环少执行了5次,因此num的结果是95。

虽然联用break、continue和label语句能够执行复杂的操作,但是如果使用过度,也会给调试带来麻烦。在此,我们建议使用label语句,一定要使用描述性标签,同时不要嵌套过多的循环。

3.6.8 with语句

with语句的作用是将代码的作用域设置到一个特定的对象当中。with语句的语法如下:

with(expression) statement

定义with语句的目的的主要是为了简化编写同一个对象的工作,如下面的例子所示:

var qs = location.search.substring(1);
var hostname = location.hostname;
var url = location.href;

上面几行代码都包含localtion对象。如果使用with语句,可以把上面的代码给成如下所示:

with(location){
    var qs = search.substring(1);
    var hostName = hostname;
    var url = href;
}

在这个重新的例子中,使用了with语句关联了location对象。这意味着with语句的代码块内部,每个变量都被认为是一个局部变量,而如果在局部环境中找不到该变量的定义,就会查询location对象中是否有同名的属性。如果发现同名属性,则以localtion对象的值作为变量的值。严格模式下不允许使用with语句,否则将视为语法错误。

3.6.9 switch语句

switch语句与if语句的关系最为紧密,而且是在其他语言中普遍使用的一种流程控制语句。ECMAScript中的switch语句的语法与其他基于C的语言非常近似。如下所示:

switch(expression){
    case value : statement;
    break;
    case value : statement;
    break;
    case value : statement;
    break;
    default : statement;
}

switch语句中的每一种情形的含义是:如果表达式等于这个值,则执行后面的语句。而break关键字会导致代码执行流跳出switch语句。如果省略break关键字,就会导致执行完当前case后,执行下一个case。最后的default关键字则用于在表达式不匹配前面任何一种形式的时候,执行机动代码。

从根本上讲,switch语句就是为了让开发人员免于编写像下面这样的代码:

if(i == 25){
    alert(25);
}else if(i == 35){
    alert(35);
}...

通过每个case后面都添加一个break语句,就可以避免同时执行多个case代码的情况,假设确实需要混合几种形式,不要忘记在代码中添加注释,说明你是有意省略了break关键字,如下所示:

switch(i){
    case 25:
        /**合并两种类型/ 
    case 35:
        alert("25 or 35");
        break;
    default:
        alert("Other");
}

虽然ECMAScript中的switch语句借鉴自其它语言,但是这个语句也有自己的特色。首先,可以在switch语句中使用任意类型的数据类型,无论是字符串,还是对象都没有问题。其次每个case值不一定是常量,可以是变量,甚至是表达式。请看下面的例子:

switch("hello world"){
    case "hello" + "world":
        alert("Greetomg was found.");
        break;
    case "goodby":
        alert("Closing was found.");
        break;
    default:
        alert("...");
}

在这个例子中,witch语句使用的就是字符串。其中,第一种形式实际上是一个字符串拼接操作值的表达式。由于这个字符串拼接结果与switch的参数相等,因此结果就会显示…。而且作为表达式的case值还可以实现下列操作:

var num = 25;
switch(true){
    case num < 0:
        alert("Less than 0.");
        break;
    case num >= 0 && num <= 10:
        alert("more than 0");
        break;
    default:
        alert('...')
}

这个例子首先在switch语句外面声明了变量num。而之所以给switch语句传递表达式true,是因为每个case都可以返回一个布尔值。这样,每个case按照顺序被求值,直到找到匹配的值或者遇到default语句为止。

猜你喜欢

转载自blog.csdn.net/s_a_g_e/article/details/80198534