0. 前言
在程式設計中,迴圈循環是個關鍵的概念。迴圈使我們能夠有效地處理重複性任務,從而避免冗長和重複的代碼,提升程式的可讀性和維護性。
那接著讓我們詳細介紹不同的框架與使用情境吧。
1. 重點
2. 內容
2.1. 基本變數迴圈
2.1.1. for 迴圈
For 迴圈算是普遍最常使用的方式,在短短的範圍內便可以定義變數與迴圈條件。
範例 1: 區域變數
以下提供的是最基礎的迴圈打印,而各位可以發現我使用的是 let 變數,定義 i 為 0,當 < 3 時迴圈執行一輪之後 i +=1,而當 i == 3 時則會停止。
for (let i = 0; i < 3; i++) { console.log(i); }
// 0
// 1
// 2
範例 2: 變數溢出
如果你翻遍網路或 GPT 基本提供的都是定義 var 變數,各位可能疑惑為何我剛要使用 let 變數。那是為了避免變數溢出,以下舉個例子是延時 1 秒觸發,結果卻不會是剛剛的 0, 1, 2 三筆,而是三個 3 的結果。
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i)
}, 1000);
}
// 3
// 3
// 3
這是因為剛剛迴圈觸發的方法在反應過來後偵測到的全域變數 i,在短暫的 1 秒之內早已到達 3,便統一打印出了 3 的結果。而利用 let 則能夠將變數限制於迴圈方法之中,依序傳入 i=0, i=1, i=2 則不會受影響。
for (let i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i)
}, 1000);
}
// 0
// 1
// 2
2.2. while 與 do-while 迴圈
while 與 do-while 在語法上相當類似,但 while 事先檢查條件,而 do-while 則是先執行。
範例 1: while 與 do-while 差異
以下範例限制在 i<0,也就是第一次執行的時候,此時 while 不會觸發,但 do-while 事先印出 0 的結果。
{
let i = 0;
while (i < 0) {
console.log(i); i++;
}
}
//
{
let i = 0;
do { console.log(i); i++; } while (i < 0)
}
// 0
2.2. 複合變數迴圈
2.2.1. for … in / for … of
針對複合變數,JavaScript 本身貼心的有提供特殊的方法,不用複雜的定義幾層迴圈。
範例 1: for … in 與 for … of 差異
為甚麼在講解變數型態時沒提及到陣列呢?就下方的例子,定義的資料長這樣: [3, 5, 7, marco:”polo”],在 JS 中的陣列是可以跨物件型態的,結構更像物件的型態。並且後續會提到,在 JS 其架構更類似 stack 與 queue 的存在。
從執行結果,可以看到 for … in 取得的是屬性名稱,於是取得陣列順序 0, 1, 2 與 marco 這個 key 值。而 for … of 取得的是屬性的值,但因為沒索引值而沒有 polo,只打印出 3, 5, 7 實際的數值。
let array = [3, 5, 7];
array.macro = "polo";
console.log(array);
// 屬性名字循環
for (let i in array) {
console.log(i);
}
// 0
// 1
// 2
// marco
// 屬性數值循環
for (let i of array) {
console.log(i);
}
// 3
// 5
// 7
2.2.2. 陣列 forEach 方法
而除了固定的迴圈表示式,有些物件也有專屬的函式可以使用。
範例 1: 陣列取值
陣列專屬的 forEach 方法也是用來取數值的方式,並可透過內部 function 的方式進行操作。
{
let array = [3, 5, 7];
array.macro = "polo";
console.log(array);
array.forEach((element) => { console.log(element); })
}
// 3
// 5
// 7
2.3. 迴圈跳脫
2.3.1. 跳過執行 — continue
範例 1: 跳過 i === 1
當迴圈執行到 i === 1 時,透過 continue 會跳過該任務,並接著後面的工作。適合例外判斷。
for (let i = 0; i < 3; i++) {
if (i === 1) { continue; } else { console.log(i); }
}
// 0
// 2
2.3.2. 脫出迴圈 — break
範例 1: 在 i === 1 脫出
相較之下,break 則會粗暴的脫出最上層的迴圈,直接中斷後續迴圈工作。適合找到解答就離開。
for (let i = 0; i < 3; i++) {
if (i === 1) { break; } else { console.log(i); }
}
// 0
2.4. 標籤迴圈
2.4.1. 跳脫到指定迴圈 — break {LABEL}
在很多時候,我們不希望一次跳脫最外層的迴圈,因此後來發明了 label 的定義方式。
範例 1: 內外迴圈
在下面的範例中,我們將外層的 while 標前為 outer,而在第 15 行可以看見,當內迴圈到達 3 時,會脫出到外迴圈接續下一份內迴圈。因此有三個階段的結果。
{
var x = 0; var y = 0;
// Outer Loop
outer: while (true) {
console.log("Outer loops: " + x);
x += 1;
y = 1;
// Inner Loop
while (true) {
console.log("Inner loops: " + y);
y += 1;
if (y === 3 && x === 3) {
// 直達指定迴圈
break outer;
} else if (y === 3) {
// 拖出所有迴圈
break;
}
}
}
// Outer loops: 0
// Inner loops: 1
// Inner loops: 2
//
// Outer loops: 1
// Inner loops: 1
// Inner loops: 2
//
// Outer loops: 2
// Inner loops: 1
// Inner loops: 2
3. 後話
理解並掌握各種迴圈結構對於編寫清晰的程式至關重要。
那基本功都差不多了,接著我們就要開始進到常用的 Array 方法,並開始透過簡易的範例來做示範。
4. 參考
[1] Loops and Iteration — MDN Web Docs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration