《JavaScript 闯关记》之语句

表达式在 JavaScript
中凡是短语,那么告诉句就是整治词发号施令。表达式用来测算出一个价值,语句用来实行因使有项事起。从本质上看,语句定义了
JavaScript
中之重大语法,语句通常采取同样要多只根本字来完成给定任务。语句可以非常简单,例如通知函数退出;也得以比较复杂,例如指定重复执行某命令的次数。下表列出了
JavaScript 大部分话的语法和用:

语句 语法 用途
break break [label]; 退出最内层循环或者退出 switch 语句,又或者退出 label 指定的语句
case case expression: switch 语句中标记一条语句
continue continue [label]; 重新开始最内层的循环或重新开始 label 指定的循环
debugger debugger; 断点器调试
default default; switch 中标记默认的语句
do-while do statement while(expression); while 循环的一种替代形式
empty ; 什么都不做
for for(init;expr;incr) statement 简写的循环结构
for-in for(var in object) statement 遍历一个对象的属性
function function name([param[],...])
{statement}
声明一个函数
if-else if (expression) statement1
[else statement2]
执行 statement1 或者 statement2
label label:statement statement 指定一个名字 label
return return [expression]; 从函数返回一个值
switch switch(expression){statement} case 或者 default 语句标记的多分支语句
throw throw expression; 抛出异常
try try {statement}
[catch {handler statement}]
[finally {cleaup statement}]
捕获异常
use strict "use strict" 对脚本和函数应用严格模式
var var name=[=expr][,...]; 声明并初始化一个或多个变量
while while(expression) statement 基本的循环结构
with with(object) statement 扩展作用域链

标准语句

if-else 语句

绝大多数编程语言中不过常用的一个言语就是 if-else 语句。以下是 if-else
语句之语法:

if (condition) statement1 [else statement2]

其中的 condition
可以是随意表达式;而且对斯表达式求值的结果不必然是布尔值。JavaScript
会自动调用 Boolean()
转换函数将此表达式的结果转换为一个布尔值。如果对 condition
求值的结果是 true,则执行 statement1,如果对 condition
求值的结果是 false,则执行
statement2。而且这半只报告句子既可是单排代码,也得是一个代码块(以同等针对花括号括起来的多行代码)。请圈下面的事例:

if (i > 25)
    console.log("Greater than 25.");              // 单行语句
else {
    console.log("Less than or equal to 25.");     // 代码块中的语句
}

业界广泛重视的特级实践是镇以代码块,即使要履行的单发一行代码。因为如此可清除人们的误会,否则可能让人口分不到头在不同尺度下而履怎样话。

switch 语句

switch 语句与 if
语句的干最密切,而且也是于其余语言中广泛使用的同种流动控制语句。JavaScript
switch 语句子之语法与另外因 C 的语言非常接近,如下所示:

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

switch
语句被之各一样种情景的意思是:“如果表达式等于是价(value),则履行后的讲话(statement)”。而
break 关键字会导致代码执行流跳出 switch 语词。如果看略 break
关键字,就会见导致执行完当前 case 后,继续执行下一个 case。最后的
default 关键字则用于在表达式不兼容前面任何一样栽情景的时候,也相当给一个
else 语句子。从根本上讲,switch
语词就是为着给开发人员免于编写像下这样的代码:

if (i === 25){
  console.log("25");
} else if (i === 35) {
  console.log("35");
} else if (i === 45) {
  console.log("45");
} else {
  console.log("Other");
}

假定同这等价格的switch语句如下所示:

switch (i) {
    case 25: 
        console.log("25");
        break;
    case 35: 
        console.log("35");
        break;
    case 45: 
        console.log("45");
        break;
    default: 
        console.log("Other");
}

由此也每个case后面还增长一个break语句,就足以免以实施多个case代码的状。假如真的需要混合几种状态,不要遗忘了当代码中补充加注,说明您是明知故问省略了break关键字。

虽然 JavaScript 中的 switch
语句子借鉴于其他语言,但此话为有温馨之特性。首先,可以以 switch
语句子被应用另外数据类型(在过剩别语言中不得不动用数值),无论是字符串,还是对象还没问题。其次,每个
case 的值不必然是常量,可以是变量,甚至是表达式。请看下面这点儿只例:

switch ("hello world") {
    case "hello" + " world": 
        console.log("Greeting was found.");
        break;
    case "goodbye": 
        console.log("Closing was found.");
        break;
    default: 
        console.log("Unexpected message was found.");
}

var num = 25;
switch (true) {
    case num < 0: 
        console.log("Less than 0.");
        break;
    case num >= 0 && num <= 10: 
        console.log("Between 0 and 10.");
        break;
    case num > 10 && num <= 20: 
        console.log("Between 10 and 20.");
        break;
    default: 
        console.log("More than 20.");
}

switch 语词首先计算 switch
关键字后的表达式,然后按照从上到下的逐一计算每个 case
后的表达式,直到执行到 case 的表达式的值与 switch
的表达式的价值当时为止。由于对每个 case 的相当操作实际是 ===
恒等运算符比较,而不是 == 相等运算符比较,因此,表达式和 case
的配合并无会见举行任何类型转换。

循环

while 语句

while
语词属于前测试循环语句,也就是说,在循环体内之代码被执行前,就见面针对出口原则求值。因引,循环体内的代码有或永远不会见受执行。以下是
while 语句的语法:

while(expression) statement

脚是一个演示:

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

do-while 语句

do-while
语句是一样栽后测试循环语句子,即只有在循环体中的代码执行之后,才见面测试出口原则。换句话说,在对标准表达式求值之前,循环体内的代码至少会叫实施同一不善。以下是
do-while 语词之语法:

do {
    statement
} while (expression);

下是一个示范:

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

for 语句

for
语词也是相同种植前测试循环语句,但它们具备在实行循环之前初始化变量和概念循环后使履行的代码的力量。以下是
for 语句之语法:

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

下是一个示范:

var count = 10;
for (var i = 0; i < count; i++){
    console.log(i);
}

这个 for 循环语句子与下部的 while 语词的机能雷同:

var count = 10;
var i = 0;
while (i < count){
    console.log(i);
    i++;
}

鉴于 JavaScript
中无有块级作用域,因此当循环之中定义的变量也可以当表看到。例如:

var count = 10;
for (var i = 0; i < count; i++){
    console.log(i);
}
console.log(i); // 10

此外,for
语句子被之初始化表达式、控制表达式和循环后表达式都是可选的。将这点儿单表达式全部简单,就会见创一个无比循环,例如:

// 无限循环
for (;;) {
    doSomething();
}

for-in 语句

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

for (property in object) statement

下面是一个演示:

for (var propName in window) {
    console.log(propName);
}

当此事例中,我们采用 for-in 循环来显示了 BOM 中 window
对象的拥有属性。每次执行循环时,都见面以 window
对象被在的一个属于性名赋值给变量
propName。这个过程会直接不绝于耳到对象被之具备属性都让枚举无异于整了。与
for 语句看似,这里控制语句被的 var
操作符也无是不可或缺的。但是,为了保使用一些变量,我们推荐方面例子中的这种做法。

JavaScript 对象的特性没有各个。因此,通过 for-in
循环输出的属性名的一一是不足预测的。具体来讲,所有属性都见面受归一不好,但回来的次第次序可能会见为浏览器而异。

如表示要迭代的目标的变量值为 nullundefinedfor-in
语句会抛来错误。虽然 ECMAScript
5双重凑巧了立同一行事;对这种气象不再抛来荒谬,而只是不实施循环体。为了保险最好要命限度的兼容性,建议以使
for-in 循环之前,先检测确认该目标的值不是 nullundefined

跳转

label 语句

使用 label 语句子可以于代码中补充加标签,以便将来下。以下是 label
语句的语法:

label: statement

下是一个演示:

start: for (var i=0; i < count; i++) {
    console.log(i); 
}

以此事例中定义的 start 标签可以以前由 breakcontinue
语句引用。加标签的话语一般都要同 for 语词等循环语词配合以。

breakcontinue 语句

breakcontinue
语句用于在循环中规范地控制代码的推行。其中,break
语词会即时退出循环,强制继续执行循环后面的讲话。而 continue
语句子虽然也是马上退出循环,但离循环后会打循环的顶部继续执行。请看下的例子:

var num = 0;

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

console.log(num);   // 4

夫例子中之 for 循环会将变量 i 由1递增至 10。在循环体内,有一个
if 语句检查 i 的价值是否足以为 5
整除(使用求模运算符)。如果是,则履行 break
语句退出循环。另一方面,变量 num0
开始,用于记录循环执行的次数。在执行 break 语句后,结果显示
4。也就是说,在变量 i 等于 5 时,循环总共执行了 4 次;而 break
语词之执行,导致了巡回在 num 再次递增之前即脱了。如果当此处把
break 替换为 continue 的说话,则可看来任何一样种植结果:

var num = 0;

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

console.log(num);   // 8

事例的结果显示 8,也就是循环总共执行了 8 次。当变量 i 等于 5
时,循环会在 num
再次递增之前退,但接下执行的凡下同样不行巡回,即i的值等于 6
的循环。于是,循环又继续执行,直到 i 等于 10 时自了。而 num
的终极价值之所以是 8,是因为 continue 语句导致它掉递增了相同次于。

breakcontinue 语句子都得以与 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++;
    }
}

console.log(num);   // 55

以斯例子中,outermost 标签表示外部的 for
语句。如果每个循环正常实施 10 次,则 num++ 语句就会见健康履 100
次。换句话说,如果简单独巡回都自然了,num 的价应是
100。但里循环中之 break
语句带了一个参数:要回去回到的签。添加这个标签的结果以招致 break
语词不仅会离内部的 for 语句(即利用变量 j
的轮回),而且也会见退出外部的 for 语句(即以变量 i
的循环)。为此,当变量 ij 都等于 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++;
    }
}

console.log(num);   // 95

当这种情形下,continue
语词会强制继续执行循环,退出内部循环,执行标循环。当 j5
时,continue 语句执行,而及时为即象征中循环少执行了 5 次,因此
num 的结果是 95

则联用 breakcontinuelabel
语句子能够履行复杂的操作,但万一以过度,也会为调试带来劳动。在是,我们建议要使用
label 语词,一定要是下描述性的竹签,同时不要嵌套过多的循环。

return 语句

return 语句子之意向是指定函数调用后的返值。return 语句之语法如下:

return [expression];

下面是一个示范:

function square(x) { return x*x; }  // 一个包含 return 语句的函数
square(2);                          // 调用结果为 4

return 语句子只能当部数体内出现,如果未是的口舌会报语法错误。当行到
return 语句子之上,函数终止执行,并赶回 expression
的值为调用程序。如果没 return
语词,则函数调用仅依次执行函数体内的每一样长告句直到函数结束,最后回来调用程序。这种情形下,调用表达式的结果是
undefinedreturn
语句经常作为函数内之最终一长达告句子出现,但连无是说如定在函数最后。return
语句可以单独行使要不要带有 expression,这样的话函数也会见往调用程序返回
undefined

鉴于 JavaScript 可以活动插入分号,因此当 return
关键字和其后的表达式之间莫克起换行。

throw 语句

throw 语句的意图是将程序运行时发生的左显式地抛弃来特别。throw
语句的语法如下:

throw expression;

expression
的价好是随机档次的。可以抛出一个意味着错误码的数字,或者隐含可读之错信息之字符串。当
JavaScript 解释器抛来特别的早晚一般以 Error 类型和其子类型。Error
对象来一个 name 属性表示错误类型,一个 message
属性用来存放在传递让构造函数的字符串,在下面的事例中,当用非法参数调用函数时便废来一个
Error 对象:

function factorial(x) {
// 如果输入参数是非法的,则抛出一个异常
    if (x < 0) throw new Error("x不能是负数");
    // 否则,计算出一个值,并正常地返回它
    for(var f = 1; x > 1; f *= x, x--) /* empty */ ;
    return f;
}

当抛来很时,JavaScript
解释器会立即终止当前着履行的逻辑,并超过反至附近的非常处理程序。如果没找到另外特别处理程序,异常就会见沿着
JavaScript 方法的词法结构以及调用栈向上传播。最终 JavaScript
将将万分当成程序错误来处理,并告于用户。

try 语句

try-catch-finally 语词是 JavaScript
中老处理机制,try-catch-finally 语句的语法如下:

try {statement} [catch {handler statement}] [finally {cleaup statement}]

try 从句定义了亟待处理的不行所当的代码块。catch 从句跟随在 try
从句后,当 try 块内某处来了要命时,调用 catch
内的代码逻辑。catch 从句后和随 finally 块,后者被放置清理代码,不管
try 块中是不是有很,finally 块内之逻辑总是会履。尽管 catch
finally 都是可选的,但 try
从句需要至少二者有与之组成总体的语句。trycatchfinally
语句块都需使用花括号括起来,这里的花括号是必备的,即使从句被只出同样条告句也未可知简单花括号。

下的代码详细的求证了 try-catch-finally 的运用目的:

try {
    // 通常来讲,这里的代码会从头执行到尾而不会产生任何问题,
    // 但有时会抛出一个异常,要么是由 throw 语句直接抛出异常,
    // 要么是通过调用一个方法间接抛出异常
}
catch(e) {
    // 当且仅当 try 语句块抛出了异常,才会执行这里的代码
    // 这里可以通过局部变量 e 来获得对 Error 对象或者抛出的其他值的引用
    // 这里的代码块可以基于某种原因处理这个异常,也可以忽略这个异常,
    // 还可以通过 throw 语句重新抛出异常
}
finally {
    // 不管 try 语句块是否抛出了异常,这里的逻辑总是会执行,终止 try 语句块的方式有:
    // 1)正常终止,执行完语句块的最后一条语句
    // 2)通过 break、continue 或 return 语句终止
    // 3)抛出一个异常,异常被 catch 从句捕获
    // 4)抛出一个异常,异常未被捕获,继续向上传播
}

其他

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;
}

以斯更写后底事例中,使用 with 语句关联了 location 对象。这表示当
with
语句之代码块内部,每个变量首先被认为是一个片变量,而设当一部分环境面临找找不交拖欠变量的概念,就见面查询
location 对象被是否生同名的特性。如果发现了跟名属性,则以 location
对象属性的价作为变量的值。

是因为大量以 with
语句会招致性降低,同时也会叫调试代码造成不便,因此于出大型应用程序时,不建议采取
with 语句。严格模式下非容许利用 with 语词,否则用视为语法错误。

debugger 语句

debugger
语词普通什么吗未开。然而,当浏览器的调试工具可用并运行的时段,JavaScript
解释器将会见以调式模式运行。实际上,这漫长告句用来发出一个断点(breakpoint),JavaScript
代码的履行会终止以断点的岗位,这时可以利用调试器输出变量的价值、检查调用栈等。例如:

function f(o) {
    if (o === undefined) {
        debugger;  // 程序会停止在该位置
    }
    // 函数的其他部分
}

use strict 语句

请参见「语法」-「严格模式」。

关卡

// 挑战一
var k;
for(i=0, j=0; i<10, j<6; i++, j++){
    k = i + j;
}
console.log(k);  // ???

// 挑战二
var nums = [12,32,54,56,78,89];
for(var n in nums){
    console.log(n);  // ???
}

// 挑战三
function showCase(value) {
    switch (value) {
        case 'A':
            console.log('Case A');
            break;
        case 'B':
            console.log('Case B');
            break;
        case undefined:
            console.log('undefined');
            break;
        default:
            console.log('Do not know!');
    }
}
showCase(new String('A'));   // ???

// 挑战四
function showCase(value) {
    switch (value) {
        case 'A':
            console.log('Case A');
        case 'B':
            console.log('Case B');
            break;
        case undefined:
            console.log('undefined');
            break;
        default:
            console.log('Do not know!');
    }
}
showCase(String('A'));   // ???

// 挑战五
var i = 0;
for (;;) {
    if (i = 2) {
        continue;
    }
    if (i = 20) {
        break;
    }
    i++;
}
console.log(i);  // ???

更多

体贴入微微信公众号「劼哥舍」回复「答案」,获取关卡详解。
关注
https://github.com/stone0090/javascript-lessons,获取最新动态。