语句通常按照从上往下的顺序被执行。JavaScript可以通过条件语句(if和switch)、循环语句(while、for和do/while)、跳转语句(break、continue、return和throw)和函数调用来改变执行序列。下面将阐述JavaScript(下文简称JS)中的语句。
表达式语句
**定义:**表达式加上分号";"组成。语法:表达式;
执行表达式语句就是计算表达式的值
x = y + z; //赋值语句
Math.cos(x); //函数调用计算余弦值,计算结果不能保留,无实际意义;
i++; //自增语句,i值增加1;
复合语句和空语句
将多条语句联合在一起,使用大括号括起来,形成复合语句(也称为:语句块),这样可以将其当成是一条语句。
注意:
- 1、语句块不需要分号结尾;
- 2、为了程序的可读性,建议语句块中的代码进行缩进;
- 3、JS中没有块级作用域,在语句块中声明的变量并不是语句块私有的。
包含0条语句的称为空语句。例如在JS循环体中至少包含一条语句,如果所有操作都在表达式中完成,此时空语句就能排上用场;
for(var i = 0; i<a.length; a[i++] = 0) ; //初始化一个数组a
在上面这个循环中,JavaScript是要求在循环体中至少需要包含一条语句,为此在后面使用一个分号来标识空语句。
**注意:**空语句的运用中,在for循环、while循环或if循环的右圆括号后的分号很不起眼,很可能造成一些致命bug,而且这些bug很难定位到;所以建议在运用空语句的时候在代码中添加注释。
声明语句
var语句
用来声明一个或者多个变量。
语法:
var name_1 [=value_1][, ..., name_n[ = value_n ]]
例如:
var i;
var j = 0;
var p,q;
var语句在函数中声明的变量为局部变量,作用域则为该函数;在代码顶层声明的变量为全局变量,整个程序可用。
var声明的变量是无法通过delete删除的。这是因为如果var声明的是全局变量,那么该变量作为window的属性,其中该属性默认的configurable的值为false,因此不能删除;如果var声明的是布局变量,那么该变量所依附的对象无法确定,所以自然也无法删除。
var语句中的变量没有指定初始化表达式,则该变量的初始值为undefined。
变量在声明他们的脚本或函数中都是有定义的,变量声明的语句会被“提前”至脚本或者函数的顶部。但是初始化的操作则还是在var声明的位置执行,在声明语句之前的变量的值是undefined。
在JS中多次声明同一个变量是可以的。
for(var i = 0; i < 10; i++) console.log(i);
for(var i = 0,j = 10; i < 10; i++,j--) console.log(i * j);
for(var i in o) console.log(i);
函数声明语句
关键字function用来定义函数
语法:
function funcname([arg1 [, arg2 [..., argn]]]) {
statements
}
其中:
- funcname:声明的函数名称
- **([arg1 [, arg2 […, argn]]]):**参数列表,使用逗号分隔;在函数调用时指代传入的实际参数。
- **{statement}:**函数体,(注意:大括号不能省略,即使只有一条语句)
函数定义不能出现在if语句,while循环或其他任何语句中,正因为声明位置的限制;所以在ECMAScript标准中并未将函数声明语句作为真正的语句。
条件语句
if语句
语法:
if(condition) statement1 else statement2
condition: 任意表达式,求值不一定是boolean值,会调用Boolean()函数转换为boolean值
语句可以是一行代码,也可以是代码块(推荐使用代码块,因为else总是和就近的if语句匹配,所以加花括号代码可读性更强,便于调试);
if(i > 25) {
alert("Greater than 25");
}else{
alert("Less than or equal to 25");
}
switch语句
switch (expression) {
case value:statement
break;
case value:statement
break;
case value:statement
break;
...
default:statement
}
注意:
- 在switch语句中可以使用任何数据类型(在很多其他语言中只能使用数值),无论字符串,还是对象都没有问题
- 每个case的值不一定是常量,可以是变量,甚至是表达式
- default表示当所有的case情况都不满足的时候执行此项,一般放在所有case标签后面,当然default是可以放在switch语句中的任何地方的。
switch语句在比较值的时候使用的是全等操作符"===",因此不会发生类型转换
循环语句
do-while语句
在循环体中的代码执行之后,才会测试出口条件,循环体内代码至少执行一次。
语法格式:
do {
statement
} while (expression)
例如:
var i = 0;
do {
i +=2;
} while (i < 10);
alert(i);
while语句
在循环体内的代码被执行之前,就会对出口条件求值。
语法格式:
while(expression) statementz
例如:
var i = 0;
while (i<10) {
i += 2;
}
for语句
语法格式:
for(initialization;expression;post-loop-expression) statement
注意:三个表达式中的任意一个都可以忽略,但是两个分号必不可少
for语句中的初始化表达式、控制表达式和循环后表达式都是可选的
for语句与while语句功能相同,也就是说 while循环做不到的,for循环同样做不到;但是while确无法完美的等价for循环,至于是为什么?下文中讲解continue的时候会给出解释。
ECMAScript中不存在块级作用域,也就是说在循环内部定义的变量也可以在外部访问到
var count = 10;
for (var i = 0; i < count; i++) {
alert(i);
}
alert(i); //10
for-in语句
用来枚举对象的属性。
语法格式:
for(property in expression) statement
例如:
for (var property in window) {
console.log(propName);
}
ECMAScript对象的属性没有顺序,利用for-in循环输出顺序不可预测,具体讲就是所有的属性都会被返回一次,具体顺序如何根据不同浏览器而定。
ECMAScript5之前,如果for-in循环中要迭代的对象变量值含有null或者undefined,则会抛出错误;在ECMAScript之后,不会抛出错误,而是不执行循环体;所有在利用for-in循环的时候,建议先确认该对象的值不是null或者undefined。
跳转语句
label语句
有语句前的标识符和冒号组成,给语句定义标签后可以在程序的任何地方通过标签名应用该条语句。
语法格式:
label:statement(注意:label必须是一个合法的JS标识符,而不能是一个保留字)
例如:
start:for(var i = 0; i < count; i++) {
alert(i);
}
定义的start标签可以由break或continue语句引用(注意:break和continue是JS中唯一可以使用语句标签的语句)。加标签的语句一般都要与for语句等循环体语句配合使用
mainloop:while(token != null) {
//代码...
continue mainloop; //跳转到下一次循环
//代码...
}
break语句和continue语句
用于在循环中精确的控制代码的执行。
break语句:立即退出最内层循环或switch语句。
var num = 0;
for (var i = 0; i < 10; i++) {
if(i % 5 == 0) {
break;
}
num ++;
}
alert(num); //4
continue语句:终止本次循环的执行并开始下一次循环的执行。
var num = 0;
for(var i = 0; i < 10; i++) {
if(i % 5 == 0) {
continue;
}
num++;
}
alert(num); //8
continue在不同循环类型中的区别:
- while循环中,会重复检测expression,检测结果为true,则循环体会从头开始执行;
- do/while循环中,会先跳至循环结尾处,重新判断循环条件,之后才会继续下一次循环;
- for循环中,先计算自增表达式,然后再检测expression表达式来判断是否执行循环体;
- for/in循环中,循环开始遍历下一个属性名,该属性名赋给了指定的变量。
上文说过while是无法完美的模拟for循环,正是因为continue在while和for循环中的区别造成的。
return语句
用于指定函数调用后的返回值。
语法格式:
return expression;(注意:return和expression之间不能换行,因为JS会自动插入分号)
return可以单独使用而不带expression,则函数会向程序返回undefined
throw语句
当程序产生异常或错误的时候,throw会显示的抛出异常。
语法格式:
thorw expression;
expression可以是任意类型。当抛出异常时,JS解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。
try/catch/finally语句
JavaScript异常处理机制,try语句中定义需要处理异常所在的代码块;catch(e)紧跟try语句块之后,当try块内发生吗异常的时候调用catch(e)内的代码逻辑;finally则跟在catch块之后,该语句块内的代码总是会被执行,无论try语句块中是否抛出异常。
语法格式:
try {
//可能会出现异常的代码;
}catch(e){
//当出现异常后该怎么处理;
}finally{
//放置清理代码(finally不经常使用)
}
其他类型语句
with语句
将代码的作用域设置到一个特定的对象中。
语法:
with(expression) statement;
**目的:**简化多次编写同一个对象的工作。
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;
使用with语句简化;
with(location) {
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}
严格模式下不允许使用with语句,否则会视为语法错误;大量使用会导致性能下降,同时给调试代码造成困难,建议还是不要使用;
参考资料
- 《JavaScript 高级程序设计 (第三版)》 人民邮电出版社
- 《JavaScript 权威指南》机械工业出版社 David Flanagan 著 淘宝前端团队 译
- 《JavaScript 语言精粹》电子工业出版社 Douglas CrockFord著