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()
是一個在網路瀏覽器中可用的全域函式。它會提示使用者輸入文字並回傳它。
for
迴圈 [ES1]for
迴圈有以下語法
for («initialization»; «condition»; «post_iteration») {
«statements»
}
第一行是迴圈的開頭,它控制主體(迴圈的其餘部分)執行頻率。它有三個部分,每個部分都是可選的
初始化
:設定迴圈的變數等。在此透過 let
或 const
宣告的變數只存在於迴圈內部。條件
:此條件會在每次迴圈迭代之前檢查。如果是假值,迴圈就會停止。後置迭代
:此程式碼會在每次迴圈迭代之後執行。因此,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
迴圈會遍歷物件的所有(自有和繼承的)可列舉屬性金鑰。當遍歷陣列時,它很少是好的選擇
以下程式碼示範這些重點
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
來遍歷陣列。 測驗
請參閱 測驗應用程式。