循環控制語句是程式流程控制的核心工具。JavaScript 提供 break、continue 以及標籤語句,讓開發者能精確控制巢狀循環的跳出與跳過行為。本文系統整理語法、行為差異、常見陷阱與現代替代方案。
break:立即終止當前循環for (let i = 1; i <= 10; i++) {
if (i === 5) break;
console.log(i);
}
// 輸出: 1 2 3 4
console.log('循環結束');
作用範圍:最近的包裹循環 (for、while、do-while) 或 switch。
continue:跳過本次迭代,直接進入下一次for (let i = 1; i <= 10; i++) {
if (i === 5) continue;
console.log(i);
}
// 輸出: 1 2 3 4 6 7 8 9 10 (缺少 5)
關鍵差異:for 循環中 continue 仍會執行迭代運算式 (i++);while/do-while 需手動更新條件變數,否則無限循環。
標籤格式:labelName: statement,可用於 break labelName、continue labelName。
break 跳出外層循環outerLoop: for (let i = 0; i < 5; i++) {
console.log(`Outer: ${i}`);
innerLoop: for (let j = 0; j < 5; j++) {
if (j > 2) break; // 只跳出 innerLoop
if (i === 2) break innerLoop; // 跳出 innerLoop (同無標籤)
if (i === 4) break outerLoop; // 直接跳出 outerLoop
console.log(` Inner: ${j}`);
}
}
console.log('Done');
輸出:
Outer: 0
Inner: 0
Inner: 1
Inner: 2
Outer: 1
Inner: 0
Inner: 1
Inner: 2
Outer: 2
Outer: 3
Inner: 0
Inner: 1
Inner: 2
Outer: 4
Done
continue 跳過外層當次迭代outerLoop: for (let i = 0; i < 3; i++) {
console.log(`Outer: ${i}`);
for (let j = 0; j < 5; j++) {
if (j === 3) continue outerLoop; // 跳過 outerLoop 剩餘迭代,直接 i++
console.log(` Inner: ${j}`);
}
}
console.log('Done');
輸出:
Outer: 0
Inner: 0
Inner: 1
Inner: 2
Outer: 1
Inner: 0
Inner: 1
Inner: 2
Outer: 2
Inner: 0
Inner: 1
Inner: 2
Done
| 規則 | 說明 |
|---|---|
| 標籤必須緊鄰循環/區塊 | label: for(...) 中間不能有其他語句 |
break label 可跳出任何區塊 | 不限於循環,可跳出 { ... } 區塊 (非嚴格模式) |
continue label 僅限循環 | 目標標籤必須標記循環語句 |
| 標籤名稱遵循識別符規則 | 建議駝峰命名,避免保留字 |
| 嚴格模式限制 | 嚴格模式下 break 僅能跳出循環/switch,不可跳出普通區塊 |
while 中 continue 導致無限循環let i = 0;
while (i < 10) {
i++;
if (i === 5) continue; // i++ 已執行,安全
console.log(i);
}
// 錯誤版本:
let j = 0;
while (j < 10) {
if (j === 5) continue; // j++ 未執行!無限循環
j++;
console.log(j);
}
forEach/map/filter 無法使用 break/continue[1,2,3,4,5].forEach(x => {
if (x === 3) break; // SyntaxError: Illegal break statement
});
替代方案:使用 for...of、傳統 for、或陣列方法 some/every (短路特性):
// 尋找第一個滿足條件的元素 (相當於 break)
const found = arr.some(x => {
if (condition(x)) { result = x; return true; } // 返回 true 停止
});
// 所有元素都滿足 (相當於無 break 完成)
const allPass = arr.every(x => condition(x));
let loop = 1;
loop: for (let i=0; i<3; i++) { ... } // 語法合法但極易混淆
// 建議標籤用大寫或 _label 後綴:OUTER_LOOP, outerLabel
// 傳統巢狀循環 + break
function findUser(users, targetId) {
for (const group of users) {
for (const user of group.members) {
if (user.id === targetId) return user; // 直接返回,無需 break
}
}
return null;
}
// 找第一個偶數的平方
const numbers = [1, 3, 4, 5, 6];
const result = numbers
.find(x => x % 2 === 0) // 4 (短路,相當於 break)
.map(x => x * x); // 16
// 過濾並處理 (相當於 continue 邏輯)
const evens = numbers.filter(x => x % 2 === 0); // [4, 6]
function* generateItems() {
for (let i = 0; i < 10; i++) {
if (i === 5) continue; // 生成器中 continue 正常工作
yield i;
}
}
for (const item of generateItems()) {
if (item > 7) break; // 外層 for...of 可用 break
console.log(item);
}
break/continue 本身極輕量,無額外開銷TypedArray + 迴圈展開、Web Workers、WASM| 語句 | 作用 | 適用循環 | 可帶標籤 | 典型用途 |
|---|---|---|---|---|
break | 終止循環 | for, while, do-while, switch | 是 | 找到目標、錯誤退出、條件滿足提前結束 |
continue | 跳過本次迭代 | for, while, do-while | 是 | 過濾無效資料、錯誤恢復、條件分支 |
label: | 標記目標循環/區塊 | 任何語句 | N/A | 巢狀循環控制、複雜流程跳轉 |
break、continue、標籤是 JavaScript 流程控制的基礎組件。雖然現代開發傾向函數式風格 (find/filter/some/for...of + 早期返回),但在處理複雜巢狀循環、狀態機、解析器、演算法核心時,標籤語句仍是最直觀、最高效的工具。掌握其語義邊界 (特別是 while 中 continue 的陷阱、forEach 不支援)、善用標籤解耦巢狀層級、並能以函數式思維重構,是寫出清晰、健壯、高效循環邏輯的關鍵。