break
和 continue
break
break
加标签:退出任何带标签的语句continue
if
语句 [ES1]if
语句的语法switch
语句 [ES3]switch
语句的第一个示例return
或 break
!default
子句检查非法值while
循环 [ES1]while
循环的示例do-while
循环 [ES3]for
循环 [ES1]for
循环的示例for-of
循环 [ES6]const
:for-of
与 for
for-await-of
循环 [ES2018]for-in
循环(避免使用) [ES1]本章涵盖以下控制流语句
if
语句 [ES1]switch
语句 [ES3]while
循环 [ES1]do-while
循环 [ES3]for
循环 [ES1]for-of
循环 [ES6]for-await-of
循环 [ES2018]for-in
循环 [ES1]break
和 continue
break
和 continue
这两个运算符可用于在我们位于循环和其他语句内部时控制它们。
break
break
有两种版本:一种带操作数,一种不带操作数。后者版本适用于以下语句:while
、do-while
、for
、for-of
、for-await-of
、for-in
和 switch
。它立即退出当前语句
for (const x of ['a', 'b', 'c']) {
console.log(x);
if (x === 'b') break;
console.log('---')
}
// Output:
// 'a'
// '---'
// 'b'
break
加标签:退出任何带标签的语句带操作数的 break
可以在任何地方使用。其操作数是一个*标签*。标签可以放在任何语句的前面,包括块。break my_label
退出标签为 my_label
的语句
: { // label
my_labelif (condition) break my_label; // labeled break
// ···
}
在以下示例中,搜索可以
result
。这在循环之后直接处理(B 行)。result
。然后我们使用 break
加标签(A 行)来跳过处理失败的代码。function findSuffix(stringArray, suffix) {
let result;
search_block: {
for (const str of stringArray) {
if (str.endsWith(suffix)) {
// Success:
= str;
result break search_block; // (A)
}// for
} // Failure:
= '(Untitled)'; // (B)
result // search_block
}
return { suffix, result };
// Same as: {suffix: suffix, result: result}
}.deepEqual(
assertfindSuffix(['notes.txt', 'index.html'], '.html'),
suffix: '.html', result: 'index.html' }
{ ;
).deepEqual(
assertfindSuffix(['notes.txt', 'index.html'], '.mjs'),
suffix: '.mjs', result: '(Untitled)' }
{ ; )
continue
continue
仅适用于 while
、do-while
、for
、for-of
、for-await-of
和 for-in
。它立即退出当前循环迭代并继续下一个迭代 – 例如
const lines = [
'Normal line',
'# Comment',
'Another normal line',
;
]for (const line of lines) {
if (line.startsWith('#')) continue;
console.log(line);
}// Output:
// 'Normal line'
// 'Another normal line'
if
、while
和 do-while
具有原则上为布尔值的条件。但是,条件只需为*真值*(如果强制转换为布尔值为 true
)即可被接受。换句话说,以下两个控制流语句是等效的
if (value) {}
if (Boolean(value) === true) {}
这是所有*假值*的列表
undefined
、null
false
0
、NaN
0n
''
所有其他值都是真值。有关更多信息,请参阅 §15.2 “假值和真值”。
if
语句 [ES1]这是两个简单的 if
语句:一个只有“then”分支,另一个同时具有“then”分支和“else”分支
if (cond) {
// then branch
}
if (cond) {
// then branch
else {
} // else branch
}
else
可以后跟另一个 if
语句,而不是块
if (cond1) {
// ···
else if (cond2) {
} // ···
}
if (cond1) {
// ···
else if (cond2) {
} // ···
else {
} // ···
}
您可以使用更多 else if
继续此链。
if
语句的语法if
语句的一般语法是
if (cond) «then_statement»
else «else_statement»
到目前为止,then_statement
一直是一个块,但我们可以使用任何语句。该语句必须以分号结尾
if (true) console.log('Yes'); else console.log('No');
这意味着 else if
不是它自己的构造;它只是一个 if
语句,其 else_statement
是另一个 if
语句。
switch
语句 [ES3]switch
语句如下所示
switch («switch_expression») {
«switch_body»
}
switch
的主体由零个或多个 case 子句组成
case «case_expression»:
«statements»
以及可选的 default 子句
default:
«statements»
switch
的执行方式如下
switch
语句的第一个示例让我们看一个例子:以下函数将 1-7 之间的数字转换为星期几的名称。
function dayOfTheWeek(num) {
switch (num) {
case 1:
return 'Monday';
case 2:
return 'Tuesday';
case 3:
return 'Wednesday';
case 4:
return 'Thursday';
case 5:
return 'Friday';
case 6:
return 'Saturday';
case 7:
return 'Sunday';
}
}.equal(dayOfTheWeek(5), 'Friday'); assert
return
或 break
!在 case 子句的末尾,执行将继续执行下一条 case 子句,除非我们使用 return
或 break
– 例如
function englishToFrench(english) {
let french;
switch (english) {
case 'hello':
= 'bonjour';
french case 'goodbye':
= 'au revoir';
french
}return french;
}// The result should be 'bonjour'!
.equal(englishToFrench('hello'), 'au revoir'); assert
也就是说,我们对 dayOfTheWeek()
的实现之所以有效,是因为我们使用了 return
。我们可以通过使用 break
来修复 englishToFrench()
function englishToFrench(english) {
let french;
switch (english) {
case 'hello':
= 'bonjour';
french break;
case 'goodbye':
= 'au revoir';
french break;
}return french;
}.equal(englishToFrench('hello'), 'bonjour'); // ok assert
可以省略 case 子句的语句,这实际上为我们提供了每个 case 子句的多个 case 表达式
function isWeekDay(name) {
switch (name) {
case 'Monday':
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
case 'Friday':
return true;
case 'Saturday':
case 'Sunday':
return false;
}
}.equal(isWeekDay('Wednesday'), true);
assert.equal(isWeekDay('Sunday'), false); assert
default
子句检查非法值如果 switch
表达式没有其他匹配项,则跳转到 default
子句。这使得它对错误检查很有用
function isWeekDay(name) {
switch (name) {
case 'Monday':
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
case 'Friday':
return true;
case 'Saturday':
case 'Sunday':
return false;
default:
throw new Error('Illegal value: '+name);
}
}.throws(
assert=> isWeekDay('January'),
() message: 'Illegal value: January'}); {
练习:switch
exercises/control-flow/number_to_month_test.mjs
exercises/control-flow/is_object_via_switch_test.mjs
while
循环 [ES1]while
循环具有以下语法
while («condition») {
«statements»
}
在每次循环迭代之前,while
都会评估 condition
while
主体将再次执行。while
循环的示例以下代码使用 while
循环。在每次循环迭代中,它都通过 .shift()
删除 arr
的第一个元素并记录它。
const arr = ['a', 'b', 'c'];
while (arr.length > 0) {
const elem = arr.shift(); // remove first element
console.log(elem);
}// Output:
// 'a'
// 'b'
// 'c'
如果条件始终评估为 true
,则 while
是一个无限循环
while (true) {
if (Math.random() === 0) break;
}
do-while
循环 [ES3]do-while
循环的工作方式与 while
非常相似,但它在每次循环迭代*之后*检查其条件,而不是之前。
let input;
do {
= prompt('Enter text:');
input console.log(input);
while (input !== ':q'); }
do-while
也可以看作是至少运行一次的 while
循环。
prompt()
是一个在 Web 浏览器中可用的全局函数。它提示用户输入文本并返回它。
for
循环 [ES1]for
循环具有以下语法
for («initialization»; «condition»; «post_iteration») {
«statements»
}
第一行是循环的*头部*,它控制*主体*(循环的其余部分)执行的次数。它包含三个部分,每个部分都是可选的
initialization
:为循环设置变量等。此处通过 let
或 const
声明的变量仅存在于循环内部。condition
:在每次循环迭代之前检查此条件。如果为假,则循环停止。post_iteration
:每次循环迭代后执行此代码。因此,for
循环大致等效于以下 while
循环
«initialization»
while («condition») {
«statements»
«post_iteration»
}
for
循环的示例例如,以下是通过 for
循环从零计数到二的方法
for (let i=0; i<3; i++) {
console.log(i);
}
// Output:
// 0
// 1
// 2
以下是通过 for
循环记录数组内容的方法
const arr = ['a', 'b', 'c'];
for (let i=0; i<arr.length; i++) {
console.log(arr[i]);
}
// Output:
// 'a'
// 'b'
// 'c'
如果我们省略头部的所有三个部分,我们将得到一个无限循环
for (;;) {
if (Math.random() === 0) break;
}
for-of
循环 [ES6]for-of
循环迭代任何*可迭代对象* – 支持 *迭代协议* 的数据容器。每个迭代值都存储在一个变量中,如头部中指定的那样
for («iteration_variable» of «iterable») {
«statements»
}
迭代变量通常通过变量声明创建
const iterable = ['hello', 'world'];
for (const elem of iterable) {
console.log(elem);
}// Output:
// 'hello'
// 'world'
但我们也可以使用已经存在的(可变)变量
const iterable = ['hello', 'world'];
let elem;
for (elem of iterable) {
console.log(elem);
}
const
:for-of
与 for
请注意,在 for-of
循环中,我们可以使用 const
。迭代变量对于每次迭代仍然可以不同(它只是在迭代过程中不能更改)。将其视为每次都在新的作用域中执行新的 const
声明。
相反,在 for
循环中,如果变量的值发生变化,我们必须通过 let
或 var
声明变量。
如前所述,for-of
适用于任何可迭代对象,而不仅仅是数组 – 例如,集
const set = new Set(['hello', 'world']);
for (const elem of set) {
console.log(elem);
}
最后,我们还可以使用 for-of
迭代数组的 [索引,元素] 条目
const arr = ['a', 'b', 'c'];
for (const [index, elem] of arr.entries()) {
console.log(`${index} -> ${elem}`);
}// Output:
// '0 -> a'
// '1 -> b'
// '2 -> c'
使用 [index, element]
,我们正在使用 *解构* 来访问数组元素。
练习:for-of
exercises/control-flow/array_to_string_test.mjs
for-await-of
循环 [ES2018]for-await-of
类似于 for-of
,但它适用于异步可迭代对象,而不是同步可迭代对象。并且它只能在异步函数和异步生成器中使用。
for await (const item of asyncIterable) {
// ···
}
异步迭代章节 中详细描述了 for-await-of
。
for-in
循环(避免使用) [ES1]for-in
循环访问对象的 all(自身和继承的)可枚举属性键。当循环遍历数组时,它很少是一个好的选择
以下代码演示了这些要点
const arr = ['a', 'b', 'c'];
.propKey = 'property value';
arr
for (const key in arr) {
console.log(key);
}
// Output:
// '0'
// '1'
// '2'
// 'propKey'
for-await-of
。for-of
。请注意,数组是可迭代的。.forEach()
。for
循环来循环遍历数组。for-in
来循环遍历数组。测验
请参阅 测验应用程序。