是什麼使得一個編程語言的新特性很棒?那就是當這個特性能夠結合多個其它特性的時候。javascript
ES2015
版本中引入的 for...of
語句就是這種狀況。java
for...of
能夠迭代數組、類數組以及任何能夠迭代的對象(maps
、sets
、DOM集合
),而且,for...of
的語句還很短。編程
在這篇文章中,我將會演示 for...of
的能力。數組
for...of
最多見的應用是對數組項進行迭代。該循環能夠高效得完成迭代,而無需其餘變量來保持索引。app
例如:編程語言
const products = ['oranges', 'apples'];
for (const product of products) {
console.log(product);
}
// 'oranges'
// 'apples'
複製代碼
for...of
循環遍歷 products
的每一項。迭代項被賦值給變量 product
.ide
數組方法 entries()
能夠用於訪問迭代項的索引。該方法在每次迭代時返回一對 [index,item]
。函數
就地解構是 for...of
的另外一個重要功能,咱們將在下一部分中對其進行詳細說明。性能
首先,咱們來看一下 for...of
循環的語法:ui
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
對象進行了解構。
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
中的每個數,並計算總和。
什麼是可迭代對象?它是支持可迭代協議的對象。
咱們能夠經過查看 Symbol.iterator
方法來肯定某個數據是否可迭代。例如,下面的例子顯示了數組是可迭代的:
const array = [1, 2, 3];
const iterator1 = array[Symbol.iterator]();
iterator1.next(); // => { value: 1, done: false }
複製代碼
若是你想了解更多信息,能夠隨時閱讀我以前的文章。
for...of
接受可迭代對象。這很棒,由於如今你能夠遍歷string
、數組、類數組、set
、map
,同時仍能夠享受 for...of
的簡潔。
JavaScript
的基礎類型 string
是可迭代的。所以,能夠輕鬆地遍歷字符串的字符。
const message = 'hello';
for (const character of message) {
console.log(character);
}
// 'h'
// 'e'
// 'l'
// 'l'
// 'o'
複製代碼
message
是一個字符串。因爲字符串可迭代的,所以 for...of
循環遍歷 message
。
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'
複製代碼
嘗試遍歷普通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]
。
你可能知道 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
語句是一個不錯的選擇。
迭代大型數組時,for...of
的執行速度可能會比經典方法慢:
const a = [/* big array */];
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
}
複製代碼
在每次迭代中調用迭代器比經過增長索引訪問的開銷更大。可是,這種細微差異在使用大型數組的應用程序中以及性能相當重要的應用程序中很是重要,不過這種狀況不多發生。
爲何說 for...of
是一顆寶石,由於:
Set
,Map
,DOM集合你首選的迭代數組項的方式是什麼?
最後:
原文地址: dmitripavlutin.com/javascript-…
點評:翻譯得很爛,還不如機翻。哈哈哈哈。