JavaScript高级程序设计之基本概念之语句第3.6讲笔记

来源:互联网 发布:淘宝网上买狗怎么寄来 编辑:程序博客网 时间:2024/06/07 05:03
ECMA-262 规定了一组语句(也称为流控制语句)。从本质上看,语句定义了ECMAScript 中的主要
语法,语句通常使用一或多个关键字来完成给定任务。语句可以很简单,例如通知函数退出;也可以比
较复杂,例如指定重复执行某个命令的次数。
3.6.1 if语句
大多数编程语言中最为常用的一个语句就是if 语句。以下是if 语句的语法:
if (condition) statement1 else statement2
其中的condition(条件)可以是任意表达式;而且对这个表达式求值的结果不一定是布尔值。
ECMAScript 会自动调用Boolean()转换函数将这个表达式的结果转换为一个布尔值。如果对condition
求值的结果是true,则执行statement1(语句1),如果对condition 求值的结果是false,则执行statement2
(语句2)。而且这两个语句既可以是一行代码,也可以是一个代码块(以一对花括号括起来的多行代码)。
请看下面的例子。
if (i > 25)
alert("Greater than 25."); // 单行语句
else {
alert("Less than or equal to 25."); // 代码块中的语句
}
IfStatementExample01.htm
不过,业界普遍推崇的最佳实践是始终使用代码块,即使要执行的只有一行代码。因为这样可以消
除人们的误解,否则可能让人分不清在不同条件下要执行哪些语句。
另外,也可以像下面这样把整个if 语句写在一行代码中:

if (condition1) statement1 else if (condition2) statement2 else statement3

但我们推荐的做法则是像下面这样:
if (i > 25) {
alert("Greater than 25.");
} else if (i < 0) {
alert("Less than 0.");
} else {
alert("Between 0 and 25, inclusive.");
}

3.6.2 do-while语句
do-while 语句是一种后测试循环语句,即只有在循环体中的代码执行之后,才会测试出口条件。
换句话说,在对条件表达式求值之前,循环体内的代码至少会被执行一次。以下是do-while 语句的
语法:
do {
statement
} while (expression);
下面是一个示例:
var i = 0;
do {
i += 2;
} while (i < 10);
alert(i);
DoWhileStatementExample01.htm
在这个例子中,只要变量i 的值小于10,循环就会一直继续下去。而且变量i 的值最初为0,每次
循环都会递增2。
像 do-while 这种后测试循环语句最常用于循环体中的代码至少要被执行一次的
情形。

3.6.3 while语句

while 语句属于前测试循环语句,也就是说,在循环体内的代码被执行之前,就会对出口条件求值。
因此,循环体内的代码有可能永远不会被执行。以下是while 语句的语法:
while(expression) statement
下面是一个示例:
var i = 0;
while (i < 10) {

i += 2;
}
WhileStatementExample01.htm
在这个例子中,变量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; i < count; i++){
alert(i);
}
ForStatementExample01.htm
以上代码定义了变量i 的初始值为0。只有当条件表达式(i<count)返回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);
}
ForStatementExample02.htm
以上代码与在循环初始化表达式中声明变量的效果是一样的。由于ECMAScript 中不存在块级作用
域(第4 章将进一步讨论这一点),因此在循环内部定义的变量也可以在外部访问到。例如:
var count = 10;
for (var i = 0; i < count; i++){

}
alert(i); //10
ForStatementExample03.htm
在这个例子中,会有一个警告框显示循环完成后变量i 的值,这个值是10。这是因为,即使i 是
在循环内部定义的一个变量,但在循环外部仍然可以访问到它。
此外,for 语句中的初始化表达式、控制表达式和循环后表达式都是可选的。将这三个表达式全部
省略,就会创建一个无限循环,例如:
for (;;) { // 无限循环
doSomething();
}
而只给出控制表达式实际上就把for 循环转换成了while 循环,例如:
var count = 10;
var i = 0;
for (; i < count; ){
alert(i);
i++;
}

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

3.6.5 for-in语句
for-in 语句是一种精准的迭代语句,可以用来枚举对象的属性。以下是for-in 语句的语法:
for (property in expression) statement
下面是一个示例:
for (var propName in window) {
document.write(propName);
}
ForInStatementExample01.htm
在这个例子中,我们使用for-in 循环来显示了BOM 中window 对象的所有属性。每次执行循环
时,都会将window 对象中存在的一个属性名赋值给变量propName。这个过程会一直持续到对象中的
所有属性都被枚举一遍为止。与for 语句类似,这里控制语句中的var 操作符也不是必需的。但是,
为了保证使用局部变量,我们推荐上面例子中的这种做法。
ECMAScript 对象的属性没有顺序。因此,通过for-in 循环输出的属性名的顺序是不可预测的。
具体来讲,所有属性都会被返回一次,但返回的先后次序可能会因浏览器而异。
但是,如果表示要迭代的对象的变量值为 null 或undefined,for-in 语句会抛出错误。
ECMAScript 5 更正了这一行为;对这种情况不再抛出错误,而只是不执行循环体。为了保证最大限度的

兼容性,建议在使用for-in 循环之前,先检测确认该对象的值不是null 或undefined。

Safari 3 以前版本的for-in 语句中存在一个bug,该bug 会导致某些属性被返回
两次。

3.6.6 label语句

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 的值是否
可以被5 整除(使用求模操作符)。如果是,则执行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
ContinueStatementExample01.htm
例子的结果显示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; j < 10; j++) {
if (i == 5 && j == 5) {
break outermost;
}
num++;
}
}
alert(num); //55

在这个例子中,outermost 标签表示外部的for 语句。如果每个循环正常执行10 次,则num++
语句就会正常执行100 次。换句话说,如果两个循环都自然结束,num 的值应该是100。但内部循环中
的break 语句带了一个参数:要返回到的标签。添加这个标签的结果将导致break 语句不仅会退出内
部的for 语句(即使用变量j 的循环),而且也会退出外部的for 语句(即使用变量i 的循环)。为此,
当变量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;
}
num++;
}
}
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;
上面几行代码都包含location 对象。如果使用with 语句,可以把上面的代码改写成如下所示:
with(location){
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}
WithStatementExample01.htm
在这个重写后的例子中,使用with 语句关联了location 对象。这意味着在with 语句的代码块
内部,每个变量首先被认为是一个局部变量,而如果在局部环境中找不到该变量的定义,就会查询
location 对象中是否有同名的属性。如果发现了同名属性,则以location 对象属性的值作为变量的值。
严格模式下不允许使用with 语句,否则将视为语法错误。

由于大量使用with 语句会导致性能下降,同时也会给调试代码造成困难,因此
在开发大型应用程序时,不建议使用with 语句。    

3.6.9 switch语句
switch 语句与if 语句的关系最为密切,而且也是在其他语言中普遍使用的一种流控制语句。
ECMAScript 中switch 语句的语法与其他基于C 的语言非常接近,如下所示:
switch (expression) {
case value: statement
break;
case value: statement
break;
case value: statement
break;
case value: statement
break;

default: statement
}
switch 语句中的每一种情形(case)的含义是:“如果表达式等于这个值(value),则执行后面的
语句(statement)”。而break 关键字会导致代码执行流跳出switch 语句。如果省略break 关键字,
就会导致执行完当前case 后,继续执行下一个case。最后的default 关键字则用于在表达式不匹配前
面任何一种情形的时候,执行机动代码(因此,也相当于一个else 语句)。
从根本上讲,switch 语句就是为了让开发人员免于编写像下面这样的代码:
if (i == 25){
alert("25");
} else if (i == 35) {
alert("35");
} else if (i == 45) {
alert("45");
} else {
alert("Other");
}
而与此等价的switch 语句如下所示:
switch (i) {
case 25:
alert("25");
break;
case 35:
alert("35");
break;
case 45:
alert("45");
break;
default:
alert("Other");
}

通过为每个case 后面都添加一个break 语句,就可以避免同时执行多个case 代码的情况。假如确
实需要混合几种情形,不要忘了在代码中添加注释,说明你是有意省略了break 关键字,如下所示:
switch (i) {
case 25:
/* 合并两种情形 */
case 35:
alert("25 or 35");
break;
case 45:
alert("45");
break;
default:
alert("Other");
}

虽然 ECMAScript 中的switch 语句借鉴自其他语言,但这个语句也有自己的特色。首先,可以在
switch 语句中使用任何数据类型(在很多其他语言中只能使用数值),无论是字符串,还是对象都没有
问题。其次,每个case 的值不一定是常量,可以是变量,甚至是表达式。请看下面这个例子:
switch ("hello world") {
case "hello" + " world":
alert("Greeting was found.");
break;
case "goodbye":
alert("Closing was found.");
break;
default:
alert("Unexpected message was found.");
}
在这个例子中,switch 语句使用的就是字符串。其中,第一种情形实际上是一个对字符串拼接操
作求值的表达式。由于这个字符串拼接表达式的结果与switch 的参数相等,因此结果就会显示
"Greeting was found."。而且,使用表达式作为case 值还可以实现下列操作:
var num = 25;
switch (true) {
case num < 0:
alert("Less than 0.");
break;
case num >= 0 && num <= 10:
alert("Between 0 and 10.");
break;
case num > 10 && num <= 20:
alert("Between 10 and 20.");
break;
default:
alert("More than 20.");
}

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

switch 语句在比较值时使用的是全等操作符,因此不会发生类型转换(例如,
字符串"10"不等于数值10)。

0 0
原创粉丝点击