如何在JavaScript中使用for迴圈

2022-11-15 06:00:38

前言

迴圈允許我們通過迴圈陣列或物件中的項並做一些事情,比如說列印它們,修改它們,或執行其他型別的任務或動作。JavaScript有各種各樣的迴圈,for迴圈允許我們對一個集合(如陣列)進行迭代。

在這篇文章中,我們將瞭解JavaScript提供的for迴圈。我們將看看for...in迴圈語句是如何在JavaScript中使用的,它的語法,它如何工作的例子,何時使用它或避免它,以及我們可以使用哪些其他型別的迴圈來代替。

為什麼使用for迴圈

在JavaScript中,就像在其他程式語言中一樣,我們使用迴圈來讀取或存取集合中的項。這個集合可以是一個陣列或一個物件。每當迴圈語句在一個集合中的項中迴圈時,我們稱之為一個迭代

有兩種方式可以存取集合中的項。第一種方式是通過它在集合中的鍵,也就是陣列中的索引或物件中的屬性。第二種方式是通過集合項本身,而不需要鍵。

for…in迴圈的定義

JavaScript的for迴圈會或迭代集合中的鍵。使用這些鍵,你就可以存取它在集合中代表的項。

集合的項可以是陣列,也可以是物件,甚至可以是字串。

for…in迴圈的語法

for迴圈具有以下語法或結構:

for (let key in value) {
  //do something here
}

在上述程式碼塊中,value是我們迭代的項的集合。它可以是物件、陣列、字串等等。key會是value每一項的鍵,在每次迭代中都會改變到列表中的下一個鍵。

注意,這裡我們使用letconst來宣告key

在物件中使用for…in迴圈

在JavaScript中使用for...in迴圈迭代物件時,其迭代的鍵或者屬性是物件自己的屬性(在上面的範例中,由key變數表示)。

由於物件可能通過原型鏈繼承資料項,其中包括物件的預設方法和屬性,以及我們可能定義的物件原型,因此我們應該使用hasOwnProperty

在下面的例子中,我們通過變數obj進行迴圈,並列印每一個屬性和值:

const obj = {
  "a": "JavaScript",
  1: "PHP",
  "b": "Python",
  2: "Java"
};

for (let key in obj) {
  console.log(key + ": " + obj[key] )
}

// Output:
// "1: PHP"
// "2: Java"
// "a: JavaScript"
// "b: Python"

請注意,鍵的迭代順序是升序的(也就是說,從數位開始,按數位的順序,然後是字母,按字母的順序)。然而,這個輸出的順序與初始化物件時建立的項的索引順序不同。

在陣列中使用for…in迴圈

在JavaScript中使用for...in迴圈來迭代陣列時,在這種情況下,key將是元素的索引。然而,索引可以按隨機順序迭代。

因此,如果我們上面展示的for...in迴圈語法結構中的value變數是一個包含五項的陣列,那麼key就不能保證是0到4。一些索引可能會在其他索引之前。關於何時可能發生這種情況的細節將在本文後面解釋。

在下面的例子中,我們對arr變數進行迴圈:

const arr = ["JavaScript", "PHP", "Python", "Java"];

for (let key in arr) {
  console.log(key + ": " + arr[key])
}

// Output:
// "0: JavaScript"
// "1: PHP"
// "2: Python"
// "3: Java"

在迴圈中,我們呈現每個陣列元素的索引和值。

在字串中使用for…in迴圈

你可以在JavaScript中使用for…in迴圈來回圈字串。然而,不推薦這麼做,因為你將在字串的索引上回圈,而不是字串本身。

在下面的例子中,我們對str變數進行迴圈:

const str = "Hello!";

for (let key in str) {
  console.log(key + ": " + str.charAt(key));
}

//Output
// "0: H"
// "1: e"
// "2: l"
// "3: l"
// "4: o"
// "5: !"

在這個迴圈中,我們要呈現每個字元的鍵或索引,以及該索引的字元。

讓我們看看JavaScript for…in迴圈最適合的情況。

使用for…in迴圈迭代物件

因為for...in迴圈只迭代物件的可列舉屬性,也就是物件自有屬性,而不是像toString這樣屬於物件原型的屬性。所以使用for...in迴圈來迭代物件是很好的。for...in迴圈提供了一個簡單的方法來迭代一個物件的屬性並最終得到它的值。

使用for…in迴圈偵錯

JavaScript for...in迴圈的另一個很好的用例是偵錯。比如,你可能想向控制檯或HTML元素列印一個物件的屬性和它的值。在這種情況下,for...in迴圈是一個不錯的選擇。

當使用for…in迴圈偵錯物件以及物件的值時,你應該始終記住,迭代是沒有順序的。也就是說,迭代的順序是隨機的。所以,存取屬性的順序可能與預期不同。

不使用for…in迴圈的情形

現在讓我們來看看for...in迴圈不是最佳選擇的情況。

陣列的有序迭代

由於使用for...in迴圈時不能保證迭代中的索引順序,如果有必要保持順序,建議不要迭代陣列。

如果你想支援像IE這樣的瀏覽器,這一點尤其重要,因為IE是按照陣列項建立的順序而不是按照索引的順序進行迭代的。這與當前現代瀏覽器的工作方式不同,後者是根據索引的升序來迭代陣列的。

舉例來說,如果你有一個包含四項的陣列,你在索引3的位置插入了一項,在現代瀏覽器中,for...in迴圈仍然會按照從0到4的順序遍歷陣列。 在IE中,當使用for...in迴圈時,它將遍歷一開始就在陣列中的四個專案,然後再遍歷在索引3的位置新增的那一項。

迭代時進行更改

對屬性的任何新增、刪除或修改都不能保證有序的迭代。應該避免在for...in迴圈中對屬性進行更改。這主要是由於它的無序性。

因此,如果你在迭代到達某一項之前刪除它,那麼這項在整個迴圈中根本就不會被存取。

同樣地,如果你對一個屬性進行修改,並不能保證這項不會被再次存取。因此,如果一個屬性被改變,它可能會在迴圈中被存取兩次而不是一次。

除此之外,如果一個屬性在迭代過程中被新增,那麼它在迭代過程中可能會被存取,也可能根本不會被存取。

由於這些情況,最好避免在for...in迴圈中對一個物件進行任何修改、刪除或新增。

下面是一個在for...in迴圈中新增元素的例子。我們可以看到第一個迴圈的結果,然後是在第一個迴圈中進行新增後的第二個迴圈的結果。

<h2>Before</h2>
<div id="loopResultsBefore"></div>
<h2>After</h2>
<div id="loopResultsAfter"></div>
const beforeDiv = document.getElementById('loopResultsBefore');

const afterDiv = document.getElementById('loopResultsAfter');

const obj = {
  "a": "JavaScript",
  1: "PHP",
  "b": "Python",
  2: "Java"
};

for (let key in obj) {
  beforeDiv.innerHTML += key + ": " + obj[key] + "<br />";
  if (!isNaN(key)) {
    obj[key - 1] = obj[key];
  }
}

for (let key in obj) {
  afterDiv.innerHTML += key + ": " + obj[key] + "<br />";
}

// Before
// 1: PHP
// 2: Java
// a: JavaScript
// b: Python
// After
// 0: PHP
// 1: Java
// 2: Java
// a: JavaScript
// b: Python

正如你在上面的例子中看到的,被新增的元素並沒有被迭代。

for迴圈的替代方案

forEach在JavaScript中是陣列原型的一個方法,它允許我們在回撥函數中遍歷陣列的元素和它們的索引。

回撥函數是你傳遞給另一個方法或函數的函數,作為該方法或函數執行的一部分而被執行。當涉及到JavaScript中的forEach時,它意味著回撥函數將在每個迭代中執行,接收迭代中的當前項作為引數。

舉例來說,下面的語句使用forEach迭代arr變數,並在console中列印value

arr.forEach((value) => console.log(value));

你也可以存取陣列的索引:

arr.forEach((value, index) => console.log(value, index));

JavaScript forEach迴圈也可以使用Object.keys()來迭代物件,把你想迭代的物件傳給它,它返回物件的自有屬性陣列:

Object.keys(obj).forEach((key) => console.log(obj[key]));

另外,如果你不需要使用Object.values()來存取屬性,你可以用forEach來直接回圈屬性的值:

Object.values(obj).forEach((value) => console.log(value));

注意,Object.values()返回項的順序與for...in相同。

總結

通過使用JavaScript for...in迴圈,我們可以迴圈物件的鍵或屬性。在迭代物件屬性或進行偵錯時,它可能很有用,但在迭代陣列或對物件進行修改時,應該避免使用for...in迴圈。

以上就是文章的所有內容,如果對你有所幫助,歡迎收藏點贊轉發~