主题
条件分支
有时我们需要根据不同条件执行不同的操作。
我们可以使用 if
语句和条件运算符 ?
(也称为“问号”运算符)来实现。
"if" 语句
if(...)
语句计算括号里的条件表达式,如果计算结果是 true,就会执行对应的代码块。
例如:
js
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
if (year == 2015) alert( 'You are right!' );
在上面这个例子中,条件是一个简单的相等性检查(year == 2015
),但它还可以更复杂。
如果有多个语句要执行,我们必须将要执行的代码块封装在大括号内:
js
if (year == 2015) {
alert( "That's correct!" );
alert( "You're so smart!" );
}
即使只有一条语句,但也建议每次使用 if 语句时都用大括号 {}
来包装代码块。这样可以提高代码可读性。
布尔转换
if(...)
语句会计算圆括号内的表达式,并将计算结果转换为布尔型。
在 类型转换(布尔型转换) 中,提到:
- 数字
0
、空字符串""
、null
、undefined
和NaN
都会被转换成false
。因为它们被称为“假值(falsy)”。 - 其他值被转换为
true
,所以它们被称为“真值(truthy)”。
所以,下面这个条件下的代码永远不会执行:
js
if (0) { // 0 是假值(falsy)
...
}
但下面的条件 —— 始终有效:
js
if (1) { // 1 是真值(truthy)
...
}
我们也可以将预先计算的布尔值传入 if 语句,像这样:
js
let cond = (year == 2015); // 相等运算符的结果是 true 或 false
if (cond) {
...
}
"else" 语句
if 语句有时会包含一个可选的 “else” 块。如果判断条件不成立,就会执行它内部的代码。
例如:
js
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
if (year == 2015) {
alert( 'You guessed it right!' );
} else {
alert( 'How can you be so wrong?' ); // 2015 以外的任何值
}
多个条件:"else if"
有时我们需要测试一个条件的几个变体。我们可以通过使用 else if 子句实现。
例如:
js
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
if (year < 2015) {
alert( 'Too early...' );
} else if (year > 2015) {
alert( 'Too late' );
} else {
alert( 'Exactly!' );
}
在上面的代码中,JavaScript 先检查 year < 2015
。如果条件不符合,就会转到下一个条件 year > 2015
。如果这个条件也不符合,则会显示最后一个 alert
。
可以有更多的 else if
块。结尾的 else
是可选的。
条件运算符 ?
有时我们需要根据一个条件去赋值一个变量。
如下所示:
js
let accessAllowed;
let age = prompt('How old are you?', '');
if (age > 18) {
accessAllowed = true;
} else {
accessAllowed = false;
}
alert(accessAllowed);
所谓的“条件”或“问号”运算符让我们可以更简短地达到目的。
这个运算符通过问号 ?
表示。有时它被称为三元运算符,被称为“三元”是因为该运算符中有三个操作数。实际上它是 JavaScript 中唯一一个有这么多操作数的运算符。
语法:
js
let result = condition ? value1 : value2;
计算条件结果,如果结果为真,则返回 value1
,否则返回 value2
。
例如:
js
let accessAllowed = (age > 18) ? true : false;
技术上讲,我们可以省略 age > 18 外面的括号。问号运算符的优先级较低,所以它会在比较运算符 > 后执行。
下面这个示例会执行和前面那个示例相同的操作:
js
// 比较运算符 "age > 18" 首先执行
//(不需要将其包含在括号中)
let accessAllowed = age > 18 ? true : false;
但括号可以使代码可读性更强,所以我们建议使用它们。
你也可以不使用问号运算符,因为比较本身就返回 true/false:
js
// 下面代码同样可以实现
let accessAllowed = age > 18;
多个 ?
使用一系列问号 ? 运算符可以返回一个取决于多个条件的值。
例如:
js
let age = prompt('age?', 18);
let message = (age < 3) ? 'Hi, baby!' :
(age < 18) ? 'Hello!' :
(age < 100) ? 'Greetings!' :
'What an unusual age!';
alert( message );
可能很难一下子看出发生了什么。但经过仔细观察,我们可以看到它只是一个普通的检查序列。
- 第一个问号检查
age < 3
。 - 如果为真 — 返回 'Hi, baby!'。否则,会继续执行冒号 ":" 后的表达式,检查
age < 18
。 - 如果为真 — 返回 'Hello!'。否则,会继续执行下一个冒号 ":" 后的表达式,检查
age < 100
。 - 如果为真 — 返回 'Greetings!'。否则,会继续执行最后一个冒号 ":" 后面的表达式,返回 'What an unusual age!'。
这是使用 if..else
实现上面的逻辑的写法:
js
if (age < 3) {
message = 'Hi, baby!';
} else if (age < 18) {
message = 'Hello!';
} else if (age < 100) {s
message = 'Greetings!';
} else {
message = 'What an unusual age!';
}
?
的非常规使用
有时可以使用问号 ?
来代替 if 语句:
js
let company = prompt('Which company created JavaScript?', '');
(company == 'Netscape') ?
alert('Right!') : alert('Wrong.');
根据条件 company =='Netscape'
,要么执行 ?
后面的第一个表达式并显示对应内容,要么执行第二个表达式并显示对应内容。
在这里我们不是把结果赋值给变量。而是根据条件执行不同的代码。
不建议这样使用问号运算符。
这种写法比 if 语句更短。但它的可读性差。
下面是使用 if 语句实现相同功能的代码,进行下比较:
js
let company = prompt('Which company created JavaScript?', '');
if (company == 'Netscape') {
alert('Right!');
} else {
alert('Wrong.');
}
因为我们的眼睛垂直扫描代码。所以,跨越几行的代码块比长而水平的代码更易于理解。
问号 ?
的作用是根据条件返回其中一个值。请正确使用它。当需要执行不同的代码分支时,请使用 if。
"switch" 语句
switch
语句可以替代多个 if 判断。
switch
语句为多分支选择的情况提供了一个更具描述性的方式。
语法
switch
语句有至少一个 case
代码块和一个 可选的 default
代码块。
就像这样:
js
switch(x) {
case 'value1': // if (x === 'value1')
...
[break]
case 'value2': // if (x === 'value2')
...
[break]
default:
...
[break]
}
- 比较
x
值与第一个case
(也就是value1
)是否严格相等,然后比较第二个case
(value2
)以此类推。 - 如果相等,
switch
语句就执行相应case
下的代码块,直到遇到最靠近的break
语句(或者直到switch
语句末尾)。 - 如果没有符合的
case
,则执行default
代码块(如果default
存在)。
举个例子
switch 的例子(高亮的部分是执行的 case 部分):
js
let a = 2 + 2;
switch (a) {
case 3:
alert( 'Too small' );
break;
case 4:
alert( 'Exactly!' );
break;
case 5:
alert( 'Too big' );
break;
default:
alert( "I don't know such values" );
}
这里的 switch 从第一个 case 分支开始将 a 的值与 case 后的值进行比较,第一个 case 后的值为 3 匹配失败。
然后比较 4。匹配,所以从 case 4 开始执行直到遇到最近的 break。
如果没有 break,程序将不经过任何检查就会继续执行下一个 case。
无 break 的例子:
js
let a = 2 + 2;
switch (a) {
case 3:
alert( 'Too small' );
case 4:
alert( 'Exactly!' );
case 5:
alert( 'Too big' );
default:
alert( "I don't know such values" );
}
在上面的例子中我们会看到连续执行的三个 alert:
- alert( 'Exactly!' );
- alert( 'Too big' );
- alert( "I don't know such values" );
任何表达式都可以成为 switch/case
的参数
switch
和 case
都允许任意表达式。
比如:
js
let a = "1";
let b = 0;
switch (+a) {
case b + 1:
alert("this runs, because +a is 1, exactly equals b+1");
break;
default:
alert("this doesn't run");
}
这里 +a
返回 1
,这个值跟 case
中 b + 1
相比较,然后执行对应的代码。
"case" 分组
共享同一段代码的几个 case
分支可以被分为一组:
比如,如果我们想让 case 3
和 case 5
执行同样的代码:
js
let a = 3;
switch (a) {
case 4:
alert('Right!');
break;
case 3: // (*) 下面这两个 case 被分在一组
case 5:
alert('Wrong!');
alert("Why don't you take a math class?");
break;
default:
alert('The result is strange. Really.');
}
现在 3
和 5
都显示相同的信息。
switch/case
有通过 case
进行“分组”的能力,其实是 switch
语句没有 break
时的副作用。因为没有 break
,case 3
会从 (*)
行执行到 case 5
。
类型很关键
强调一下,这里的相等是 严格相等。被比较的值必须是相同的类型才能进行匹配。
比如,我们来看下面的代码:
js
let arg = prompt("Enter a value?");
switch (arg) {
case '0':
case '1':
alert( 'One or zero' );
break;
case '2':
alert( 'Two' );
break;
case 3:
alert( 'Never executes!' );
break;
default:
alert( 'An unknown value' );
}
- 在 prompt 对话框输入
0
、1
,第一个 alert 弹出。 - 输入
2
,第二个 alert 弹出。 - 但是输入
3
,因为 prompt 的结果是字符串类型的"3"
,不严格相等===
于数字类型的3
,所以case 3
不会执行!因此case 3
部分是一段无效代码。所以会执行default
分支。