JavaScript/迴圈
JavaScript 透過關鍵字 for 和 while 支援程式碼塊的重複執行。Array 資料型別(以及類似的資料型別)的 forEach 方法提供了類似的行為。
for 語句的語法是:for (<初始表示式>; <條件>; <最終表示式>) { <程式碼塊> }。它的執行基於以下規則
初始表示式被執行 - 對於整個for語句只執行一次。通常,它宣告並初始化一個或多個變數 - 通常是具有整數值的數字。有時變數的宣告是在for語句之上進行的。條件被評估。如果它返回true,則執行步驟 3。如果它返回false,則for語句終止。- 程式碼塊被執行。
最終表示式被執行。通常,它會遞增或遞減作為條件部分的變數。- 迴圈從步驟 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);
}
迴圈的這種巢狀在所有以下結構中也是可能的。
有時只有部分或整個程式碼塊需要執行。這可以透過一個或多個 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
}
一個現實的場景是遍歷資料庫搜尋結果的迴圈,其中在迴圈的中間斷開了與資料庫的連線。
您可以在所有形式的迴圈中使用 continue 和 break。
語句的語法是:do { <程式碼塊> } while (<條件>)。它的執行基於以下規則
- 程式碼塊被執行。因為這是第一步,所以程式碼塊至少執行一次。如果您想確保在任何情況下都發生某些事情,這將很有幫助。
條件被評估。如果它返回true,則再次呼叫步驟 1。如果它返回false,則迴圈終止。請注意,沒有專門的部分可以用來操作條件中檢查的變數。這必須在程式碼塊中與其他語句一起完成。
"use strict";
let counter = 100;
do {
counter++;
alert(counter); // ... or some logging
} while (counter < 10);
while (<條件>) { <程式碼塊> } 的語法與之前的 do { <程式碼塊> } while (<條件>) 非常相似。唯一的區別是條件是在程式碼塊之前檢查,而不是之後。
此語言結構用於遍歷物件的屬性。它的語法是: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 (<變數> 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
這兩個語言結構的差異在示例中總結。
"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!
}
如果您正在尋找一個迴圈來處理物件的鍵和值,則比上面顯示的 for..in 與 myObj[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..in 或 for..of 語言結構這樣的“核心”語言元素。它們分別是 Object 和 Array 資料型別的方法。
資料型別 Array 提供了 forEach() 方法。它遍歷陣列的元素,依次返回一個元素。有趣的是,它以函式作為引數。這與各種 for 和 while 迴圈不同。此類函式通常稱為 回撥函式。
方法呼叫非常簡單: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() 方法
- 該方法可用於可迭代物件,如 Array、Map、Set。資料型別 Object 不可迭代。
- 該方法僅遍歷具有數字鍵的元素,這是陣列的常見情況。
另請參見