跳至內容

JavaScript/迴圈

來自華夏公益教科書



JavaScript 透過關鍵字 forwhile 支援程式碼塊的重複執行。Array 資料型別(以及類似的資料型別)的 forEach 方法提供了類似的行為。

for (;;) {}

[編輯 | 編輯原始碼]

for 語句的語法是:for (<初始表示式>; <條件>; <最終表示式>) { <程式碼塊> }。它的執行基於以下規則

  1. 初始表示式 被執行 - 對於整個 for 語句只執行一次。通常,它宣告並初始化一個或多個變數 - 通常是具有整數值的數字。有時變數的宣告是在 for 語句之上進行的。
  2. 條件 被評估。如果它返回 true,則執行步驟 3。如果它返回 false,則 for 語句終止。
  3. 程式碼塊被執行。
  4. 最終表示式 被執行。通常,它會遞增或遞減作為 條件 部分的變數。
  5. 迴圈從步驟 2 處重複。
for (let i = 0; i < 10; i++) {
  // a block of statements
}

示例:顯示偶數的平方系列;顯示從 0 到 10 的數字的總和。

"use strict";

const upperLimit = 10;
let sum = 0;
let tmpString = "";

for (let i = 0; i <= upperLimit; i++) {
  sum = sum + i;
  if (i % 2 === 0) {
    tmpString += i*i + "; "
  }
}
alert ("The sum is: " + sum + ". The square numbers are: " + tmpString);

可選語法部分

[編輯 | 編輯原始碼]

初始表示式條件最終表示式 是可選的。如果您省略其中一個或多個,您的指令碼將執行其他有用的語句來控制迴圈。以下是一些示例

"use strict";

// an infinite loop if you do not terminate it with 'break' (see below)
for (;;) {
  // ...
  break;
}

const answer = prompt("With which start value shall the loop begin?");
let i = Number(answer);
for (; i >= 0 && i < 10; i++) {
  // the start value is computed above the loop
}

for (let i = 0; i < 10; ) {
  // ...
  if (true) { // an arbitrary other condition to control the increment
    i++;
  }
}

for 迴圈可以巢狀。您可以在第一個(或“外層”)迴圈的程式碼塊中使用第二個(或“內層”)迴圈。

"use strict";

const maxInner = 10;
const maxOuter = 4;
let myString = "";

for (let o = 1; o <= maxOuter; o++) {
  myString = "";
  // Be careful. It's easy to confuse inner and outer loop variables.
  for (let i = 1; i <= maxInner; i++) {
    myString = myString + o*i + ", ";
  }
  alert(myString);
}

迴圈的這種巢狀在所有以下結構中也是可能的。

continue / break

[編輯 | 編輯原始碼]

有時只有部分或整個程式碼塊需要執行。這可以透過一個或多個 if / else 語句來實現。如果合適,可以使用關鍵字 continue 來縮短這種條件語句。如果遇到 continue,則跳過程式碼塊的剩餘部分,並執行上面的步驟 4 最終表示式

"use strict";

for (let i = 0; i <= 6; i++) {  
  if (i === 5) { 
    continue;   // skip the rest of the block
  }
  alert(i);     // 0, 1, 2, 3, 4, 6
}

這個例子非常簡單。它在 i 等於 5 的情況下跳過程式碼塊的下部。當然,它也可以用其他方式表達。一個更現實的例子是遍歷資料庫搜尋結果的迴圈,它跳過對具有特定狀態的行進行復雜處理的部分。

break 關鍵字與 continue 關鍵字類似,但更嚴格。它不僅跳過程式碼塊的剩餘部分,而且還終止整個迴圈。

"use strict";

for (let i = 0; i <= 6; i++) {  
  if (i === 5) { 
    break;      // terminal the loop
  }
  alert(i);     // 0, 1, 2, 3, 4
}

一個現實的場景是遍歷資料庫搜尋結果的迴圈,其中在迴圈的中間斷開了與資料庫的連線。

您可以在所有形式的迴圈中使用 continuebreak

do {} while ()

[編輯 | 編輯原始碼]

語句的語法是:do { <程式碼塊> } while (<條件>)。它的執行基於以下規則

  1. 程式碼塊被執行。因為這是第一步,所以程式碼塊至少執行一次。如果您想確保在任何情況下都發生某些事情,這將很有幫助。
  2. 條件 被評估。如果它返回 true,則再次呼叫步驟 1。如果它返回 false,則迴圈終止。請注意,沒有專門的部分可以用來操作條件中檢查的變數。這必須在程式碼塊中與其他語句一起完成。
"use strict";

let counter = 100;
do {
  counter++;
  alert(counter);  // ... or some logging
} while (counter < 10);

while () {}

[編輯 | 編輯原始碼]

while (<條件>) { <程式碼塊> } 的語法與之前的 do { <程式碼塊> } while (<條件>) 非常相似。唯一的區別是條件是在程式碼塊之前檢查,而不是之後。

for (x in Object) {}

[編輯 | 編輯原始碼]

此語言結構用於遍歷物件的屬性。它的語法是:for (<變數> in <物件>) { <程式碼塊> }。變數接收物件的每個屬性的 - 一個接一個。對於每個屬性,程式碼塊都執行一次。

"use strict";

const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};

for (const key in myObj) {
  alert(key); // firstName, familyName, born
  // alert(myObj[key]);  // if you want to see the values
}

陣列是專門的物件。因此,可以在陣列上使用 for..in。陣列的鍵是整數,從 0 開始 - 這正是從陣列中提取的內容。

"use strict";

const myArray = ["certo", "uno", "dos", "tres"];
for (const key in myArray) {
  alert(key); // 0, 1, 2, 3
  // alert(myArray[key]);  // if you want to see the values
}

陣列也接受非數字鍵,例如,myArray["four"] = "cuatro";for..in 迴圈處理這種非數字鍵 - 與下面的 for..of 迴圈相反,也與頁面頂部的傳統 for 迴圈相反。

另請參見:MDN:for..in

for (x of Array) {}

[編輯 | 編輯原始碼]

此語言結構用於遍歷陣列。它的語法是:for (<變數> of <可迭代物件>) { <程式碼塊> }。變數接收陣列的所有 - 一個接一個。對於每個值,程式碼塊都執行一次。

此定義聽起來與上面 for..in 的定義類似。但它們之間存在顯著的差異

  • 它返回的是 ,而不是陣列的 索引
  • 它只適用於所有 可迭代 物件(Array、Map、Set 等)。資料型別 'object' 不可迭代。
  • 它只適用於數字型別的鍵。非數字型別的 索引 會被靜默地忽略。
"use strict";

const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";

for (const myValue of myArray) {
  alert(myValue); // cero, uno, dos, tres. No 'cuatro' because the key is a string.
}

另請參見:MDN:for..of

for..in 與 for..of 的區別

[編輯 | 編輯原始碼]

這兩個語言結構的差異在示例中總結。

"use strict";

const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";

// for..of not allowed on true objects; only for..in is possible.
for (const x of myObj) {};  // error

for (const x in myArray) {
  alert(x); // 0, 1, 2, 3, four
}

for (const x of myArray) {
  alert(x); // cero, uno, dos, tres. NO cuatro!
}

Object.entries() 方法

[編輯 | 編輯原始碼]

如果您正在尋找一個迴圈來處理物件的鍵和值,則比上面顯示的 for..inmyObj[key] 的組合更直接的方法。資料型別 Object 提供了 entries() 方法,該方法返回一個數組。該陣列的每個元素都包含一個包含兩個值的陣列:屬性鍵和屬性值。換句話說:entries() 方法的返回值是一個二維陣列。而且,與陣列一樣,您應該將其與 for..of 結合使用。

"use strict";

const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";

for (const [key, val] of Object.entries(myObj)) {
  alert(key + ' / ' + val);
}
for (const [key, val] of Object.entries(myArray)) {
  alert(key + ' / ' + val); // 'four / cuatro' is included
}

提示:Object.entries() 以及以下 Array.forEach() 方法不是像關鍵字或 for..infor..of 語言結構這樣的“核心”語言元素。它們分別是 ObjectArray 資料型別的方法。

Array.forEach() 方法

[編輯 | 編輯原始碼]

資料型別 Array 提供了 forEach() 方法。它遍歷陣列的元素,依次返回一個元素。有趣的是,它以函式作為引數。這與各種 forwhile 迴圈不同。此類函式通常稱為 回撥函式

方法呼叫非常簡單:myArray.forEach(myFunction)。可能令人困惑的是,函式呼叫 可以用多種方式縮寫。

第一個示例顯示了顯式函式呼叫。它定義了函式 myFunction,它也接受單個引數。當 myFunction 被 forEach() 呼叫時,下一個陣列元素被插入到 myFunction 的引數中。

"use strict";

// function definition (the function is not called here!)
function myFunction(element) {
  alert("The element of the array is: " + element)
};

// a test array
const myArray = ['a', 'b', 'c'];

// iterate over the array and invoke the function once per array element
myArray.forEach(myFunction);

以下示例顯示了函式呼叫語法的一些縮寫。

"use strict";

// the 'arrow' syntax
const myFunction = 
  (element) => {
    alert("The element of the array is: " + element)
  };

// same code without line breaks:
// const myFunction = (element) => {alert("The element of the array is: " + element)};

const myArray = ['a', 'b', 'c'];
myArray.forEach(myFunction);
"use strict";
const myArray = ['a', 'b', 'c'];

// Define the function directly as the argument of the forEach(). Such
// functions are called 'anonymous' functions.
myArray.forEach((element) => {alert("The element of the array is: " + element)});
"use strict";
const myArray = ['a', 'b', 'c'];

// in simple cases, more syntactical elements are optional
myArray.forEach(element => alert("The element of the array is: " + element));

使用哪種語法取決於您的偏好。

在許多情況下,被呼叫函式執行副作用,例如日誌記錄。要計算所有陣列元素的值,有必要使用閉包 的技術。在以下示例中,變數 sum 未在外部上下文中定義,也不在匿名函式中定義。

"use strict";

const myArray = [3, 0, -1, 2];
let sum = 0;

myArray.forEach(element => sum = sum + element);
alert(sum);

總而言之,以下規則適用於 forAll() 方法

  • 該方法可用於可迭代物件,如 ArrayMapSet。資料型別 Object 不可迭代。
  • 該方法僅遍歷具有數字鍵的元素,這是陣列的常見情況。

另請參見

MDN:forEach()
MDN:迭代方法
...在另一個頁面上提供(點選這裡)。

另請參見

[編輯 | 編輯原始碼]
華夏公益教科書