為什麼說for...of是JS中的一顆寶石

劉小夕發表於2020-03-31

是什麼使得一個程式語言的新特性很棒?那就是當這個特性可以結合多個其它特性的時候。

ES2015 版本中引入的 for...of 語句就是這種情況。

for...of 可以迭代陣列、類陣列以及任何可以迭代的物件(mapssetsDOM集合),並且,for...of 的語句還很短。

在這篇文章中,我將會演示 for...of 的能力。

1. 陣列迭代

for...of 最常見的應用是對陣列項進行迭代。該迴圈可以高效得完成迭代,而無需其他變數來保持索引。

例如:

const products = ['oranges', 'apples'];

for (const product of products) {
  console.log(product);
}
// 'oranges'
// 'apples'
複製程式碼

for...of 迴圈遍歷 products 的每一項。迭代項被賦值給變數 product.

陣列方法 entries() 可以用於訪問迭代項的索引。該方法在每次迭代時返回一對 [index,item]

就地解構是 for...of 的另一個重要功能,我們將在下一部分中對其進行詳細說明。

1.1 就地解構

首先,我們來看一下 for...of 迴圈的語法:

for (LeftHandSideExpression of Expression) {
  // statements
}
複製程式碼

LeftHandSideExpression 表示式可以替換為任意賦值表示式左側的內容。

在前面的示例中,LeftHandSideExpression 是一個變數宣告 const product ,甚至是一個解構 const [index,product]

因此,for...of 的語法支援實現迭代項的解構。

讓我們遍歷一個物件陣列,提取每個物件的 name 屬性:

const persons = [
  { name: 'John Smith' },
  { name: 'Jane Doe' }
];

for (const { name } of persons) {
  console.log(name);
}
// 'John Smith'
// 'Jane Doe'
複製程式碼

const { name } of persons 迴圈迭代 persons 物件陣列,並且就地將 person 物件進行了解構。

2. 類陣列迭代

for...of 可以用於迭代類陣列物件。arguments 是函式體內的特殊變數,包含函式的所有引數,這是一個經典的類陣列物件。

讓我們寫一個求和函式 sum(num1, num2, ..., numN)

function sum() {
  let sum = 0;
  for (const number of arguments) {
    sum += number;
  }
  return sum;
}

sum(1, 2, 3); // => 6
複製程式碼

在每次迭代中,for...of 迴圈遍歷類陣列 arguments 中的每一個數,並計算總和。

3. 快速瞭解可迭代

什麼是可迭代物件?它是支援可迭代協議的物件。

我們可以通過檢視 Symbol.iterator 方法來確定某個資料是否可迭代。例如,下面的例子顯示了陣列是可迭代的:

const array = [1, 2, 3];
const iterator1 = array[Symbol.iterator]();
iterator1.next(); // => { value: 1, done: false }
複製程式碼

如果你想了解更多資訊,可以隨時閱讀我之前的文章

for...of 接受可迭代物件。這很棒,因為現在你可以遍歷string、陣列、類陣列、setmap,同時仍可以享受 for...of 的簡潔。

4. 字串迭代

JavaScript 的基礎型別 string 是可迭代的。因此,可以輕鬆地遍歷字串的字元。

const message = 'hello';

for (const character of message) {
  console.log(character);
}
// 'h'
// 'e'
// 'l'
// 'l'
// 'o'
複製程式碼

message 是一個字串。由於字串可迭代的,因此 for...of 迴圈遍歷 message

5. Map 和 Set 迭代

Map 是一個特殊的物件,將鍵與值相關聯。鍵可以是任何基本型別(通常是 string,但可以是 number 等)。

幸運的是,Map 也是可迭代的(在鍵/值對上進行迭代),並且 for...of 可以輕鬆地迴圈迭代所有鍵/值對。

一起看一下:

const names = new Map();
names.set(1, 'one');
names.set(2, 'two');

for (const [number, name] of names) {
  console.log(number, name);
}
// logs 1, 'one'
// logs 2, 'two'
複製程式碼

for (const [number, name] of names) 迭代 names 的鍵值對。

在每個迴圈中,迭代器都會返回一個陣列 [key,value] ,並使用 const [number,name] 立即對這對陣列進行解構。

以相同的方式可以遍歷 Set 的項:

const colors = new Set(['white', 'blue', 'red', 'white']);

for (let color of colors) {
  console.log(color);
}
// 'white'
// 'blue'
// 'red'
複製程式碼

6. 迭代普通的JavaScript物件

嘗試遍歷普通JS物件的屬性/值總是很痛苦。過去,我通常使用 Object.keys() 獲取物件的鍵,然後使用 forEach 來迭代鍵陣列。【譯者:這不代表本人觀點,我比較喜歡用 for...in 遍歷物件,不過需要注意for...in的副作用哈】

const person = {
  name: 'John Smith',
  job: 'agent'
};

Object.keys(person).forEach(prop => {
  console.log(prop, person[prop]);
});
// 'name', 'John Smith'
// 'job', 'agent'
複製程式碼

新的 Object.entries() 函式與 for...of 組合使用是個不錯的選擇:

const person = {
  name: 'John Smith',
  job: 'agent'
};

for (const [prop, value] of Object.entries(person)) {
  console.log(prop, value);
}
// 'name', 'John Smith'
// 'job', 'agent'
複製程式碼

Object.entries(person) 返回一個鍵和值的元組陣列:[[''name','John Smith'],['job','agent']]。然後,使用 for...of 迴圈遍歷陣列,並將每個元組解構為 const [prop,value]

7. 遍歷DOM集合

你可能知道 HTMLCollection 令人沮喪。主要是因為 HTMLCollection 是一個類陣列的物件(而不是常規陣列),所以我們無法使用陣列的方法。

例如,每個 DOM 元素的 children 屬性都是 HTMLCollection 。好在 for...of 可以在類似陣列的物件上進行迭代,因此我們可以輕鬆地迭代 children

const children = document.body.children;

for (const child of children) {
  console.log(child); // logs each child of <body>
}
複製程式碼

此外,for...of 可以迭代 NodeList 集合(可迭代)。例如,函式 document.querySelectorAll(query) 返回一個 NodeList

const allImages = document.querySelectorAll('img');

for (const image of allImages) {
  console.log(image); // log each image in the document
}
複製程式碼

如果你想遍歷 DOM 中的不同種類的集合,那麼 for...of 語句是一個不錯的選擇。

8. 效能

迭代大型陣列時,for...of 的執行速度可能會比經典方法慢:

const a = [/* big array */];
for (let i = 0; i < a.length; i++) {
  console.log(a[i]);
}
複製程式碼

在每次迭代中呼叫迭代器比通過增加索引訪問的開銷更大。但是,這種細微差別在使用大型陣列的應用程式中以及效能至關重要的應用程式中非常重要,不過這種情況很少發生。

9. 總結

為什麼說 for...of 是一顆寶石,因為:

  • 它簡明扼要
  • 它接受迭代器,包括陣列,字串,SetMap,DOM集合
  • 它接受類陣列物件
  • 迭代的專案可以在就地解構。

你首選的迭代陣列項的方式是什麼?

最後:

原文地址: dmitripavlutin.com/javascript-…

點評:翻譯得很爛,還不如機翻。哈哈哈哈。

掘金使用

相關文章