for…of
1. 前言
在編程中最常見的就是對數據的遍歷操作,ES5 有針對數組和對象的遍歷方法,但這些方法或多或少地都會存在一定的問題。為了統一解決這些問題,ES6 給出了終極的解決方案 ——for...of。
for...of 對于可迭代的對象(包括:內置的 String、Array、類似數組的對象(arguments 或 NodeList)、TypedArray、Map、Set,和用戶定義的可迭代對象等)上創建一個迭代循環,它不局限于數組下的循環,只要是可迭代的對象就可以被 for...of 進行循環。
2. 基本語法
2.1 語法使用
for (const iterator of iterable) {
// 執行語句
}
參數解釋:
| 參數 | 描述 |
|---|---|
iterator |
在每次迭代中,將不同屬性的值分配給變量,用于循環中語句的使用; |
iterable |
被迭代枚舉的對象。 |
2.2 迭代 Array
for...of 最常用的場景就是對數組的迭代,也是取代 for、forEach 的最好選擇。
let arr = [10, 20, 30];
for (let value of arr) {
value += 1;
console.log(value);
}
// 11
// 21
// 31
上面的代碼中對 value 值進行加 1 操作,如果 value 值不能被修改,也可以使用 const 來定義 value。
2.3 迭代字符串
for...of 可以迭代字符串,迭代后的結果是把字符進行分割,得到每個單個字符。
let str = '慕課';
for (let value of str) {
console.log(value);
}
// 慕
// 課
2.4 迭代 TypedArray
let iterable = new Uint8Array([0x00, 0xff]);
for (let value of iterable) {
console.log(value);
}
// 0
// 255
2.5 迭代 Set 和 Map
在 Set 和 Map 章節中我們就說到了,Set 和 Map 可以使用 for...of 來進行循環,主要因為 Set 和 Map 具有可迭代屬性。
let setArr = new Set([1, 1, 2, 2, 3, 3]);
for (let value of setArr) {
console.log(value);
}
// 1
// 2
// 3
上面的代碼需要注意的是,迭代的是 new Set() 后的結果,new Set() 會對數組進行去重操作,所以得到以上結果。
let map = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let value of map) {
console.log(value);
}
// ["a", 1]
// ["b", 2]
// ["c", 3]
上面的代碼中使用 new Map() 傳入一個二維數組,這里需要注意的是,迭代的結果是一個帶有 key 和 value 的數組,所以也可以用數組解構的方式 把 key 和 value 的值取出來,直接使用:
for (let [key, value] of map) {
console.log(key, value);
}
// a 1
// b 2
// c 3
2.6 迭代類數組對象
1. 迭代 argument 對象
我們知道在函數中可以使用 Argument 對象拿到在調用函數時拿到傳遞的參數,因為 arguments 不是一個 Array,它屬于類數組,可以借助 call 來得到一個數組。[].slice.call(arguments), 而使用 for...of 可以直接對 arguments 循環,得到的結果也只是傳入的參數。這個可以很方便地去循環類數組對象。
function argfn() {
for (let argument of arguments) {
console.log(argument);
}
}
argfn(1,2,3)
// 1
// 2
// 3
上面的代碼可以看出來,打印的結果只有 1、2、3 沒有類數組上的其他屬性值。
2. 迭代 DOM 集合
其實最常見的數組對象是得到網頁上的 DOM 元素的集合,它也是一個類數組對象。比如一個 NodeList 對象:下面的例子演示給每一個 p 標簽添加一個 “read” 類。
//注意:這只能在實現了NodeList.prototype[Symbol.iterator]的平臺上運行
let prags = document.querySelectorAll("p");
for (let value of prags) {
value.classList.add("read");
}
上面的代碼,需要在在帶有 p 的標簽的 html 文件中運行。
3 知識對比
ES5 中提供了很多遍歷的方法,下面我們與之一一對比看看 for...of 有什么優勢。
3.1 對比 for
最原始的語法是 for 循環語句,但是這種寫法比較麻煩,每個步驟的信息都需要手動地去處理。
const fib = [1,1,2,3,5,8,13...]; // 斐波那切數列
for (let index = 0; index < fib.length; index++) {
console.log(fib[index]);
}
3.2 對比 forEach
數組中內置了 forEach 方法,這個方法的致命缺點就是不能跳出循環,break 命令和 return 命令都不能奏效。
fib.forEach((value) => {
console.log(value);
});
3.3 對比 for…in
for...in用以遍歷對象的屬性,for...of用以遍歷數據,就像數組中的值一樣;for...in主要是針對對象循環而設計的,對于數組,鍵就是數字,但是在for...in循環中是以字符串作為鍵名;for...in循環不僅遍歷數字鍵名,還會遍歷手動添加的其他鍵,甚至包括原型鏈上的鍵;- 某些情況下,
for...in循環以任意順序遍歷鍵名,主要是因為對象在內存中的數據類型決定的。
for (let index in fib) {
console.log(fib[index]);
}
3.4 for...of 的優點
- 有著同
for...in一樣的簡潔語法,但是沒有for...in那些缺點; - 不同于
forEach方法,它可以與break、continue和return配合使用; - 提供了遍歷所有數據結構的統一操作接口。
for (let n of fib) {
if (n > 520)
break;
console.log(n);
}
當迭代項大于 520 時 break 語句會跳出 for...of 循環。
4. 小結
- 對于數組的處理盡量使用
for...of去迭代數據; - 如果要遍歷的是對象,并且沒有順序的限制可以使用
for...in方式遍歷對象更好的處理數據。
殺手Kira ·
2025 imooc.com All Rights Reserved |