Iterator 和 for…of 迴圈

下一個發表於2019-02-17

Iterator 和 for…of 迴圈

Iterator(遍歷器)意義

為Array、Object、Map、Set四種資料集合,提供統一的介面機制來處理所有不同的資料結構 。

任何資料結構,只要部署 Iterator 介面,就可以完成遍歷操作(即依次處理該資料結 構的所有成員) 。

介面

//遍歷器介面 
interface Iterable{
    [Symbol.iterator]():Iterator,
}
//指標物件
interface Iterator{
    next(value?:any):IterationResult,
}
//返回結果
interface IterationResult{
    value:any,
    done:boolean
}

生成器
Generator 函式的呼叫方法與普通函式一樣,也是在函式名後面加上一對圓括號。不同 的是 ,
呼叫 Generator 函式後,該函式並不執行 , 返回的也不是函式執行結果 , 而是一個指 向內 部狀態
的指標物件, 也就是上一章介紹的遍歷器物件 Iterator Object ) 。
呼叫 Generator 函式返回一個遍歷器物件,代表 Generator 函式的內部指標 。 以
後,每次呼叫遍歷器物件的 next 方法,就會返回 一個有著 value 和 done 兩個屬性的物件 。
value 屬性表示當前的內部狀態的值,是 yield 語句後面那個表示式的值 : done 屬性是一個
布林值,表示是否遍歷結束

作用

  1. 為各種資料結構提供一個統一 的、簡便的訪問介面;
  2. 使得 資料結構的成員能夠按某種次序排列;
  3. ES6 創造了 一種新的遍歷命令一for . . . of 迴圈, Iterator 介面 主要供 for … of 消費。

過程

  1. 建立一個指標物件,指向當前資料結構的起始位置 。 也就是說,遍歷器物件本質上就是 一個指標物件 。
  2. 第一次呼叫指標物件的 next 方法,可以將指標指向資料結構的第 一個成員 。
  3. 第二次呼叫指標物件的 next 方法,指標就指向資料結構的第二個成員 。
  4. 不斷呼叫指標物件的 next 方法,直到它指向資料結構的結束位置 。

原理

每次呼叫 next 方法都會返回資料結構的當前成員的資訊。具體來說,就是返回一個包含 value 和 done 兩個屬性的物件。其中, value 屬性是當前成員的值, done 屬性是一個布林值

與其他遍歷語法的比較

以陣列為例, JavaScript 提供了多種遍歷語法。最原始的寫法就是 for 迴圈 。

//麻煩
for (var index = 0; index < myArray.length ; index++) { 
    console.log(myArray[index]);  
} 
// 不能跳出
myArray.forEach(function (value) {
    console.log(value) ; 
})

//被設計用來遍歷物件,而不是陣列
for(let i in myArray){
    console.log(i)
}
//簡潔,可跳出,統一介面
for(let i of myArray){
    console.log(i)
}

//for ... of的等價寫法
let iterator = myArray[Symbol.iterator]();
let item = iterator.next();
while(!item.done){
    console.log(item.value);
    item = iterator.next();
}

這種寫法比較麻煩,因此陣列提供了內建的 forEach 方法。

這種寫法的問題在於,無法中途跳出 forEach 迴圈, break 命令或 return 命令都不能 奏效

for … in迴圈可以遍歷陣列的鍵名。

for … in 迴圈有幾個缺點。

  • 陣列的鍵名是數字,但是 for … in 迴圈是以字串作為鍵名,“0”、“ 1 ”、" 2 ”等。
  • for … in 迴圈不僅可以遍歷數字鍵名,還會遍歷手動新增的其他鍵,甚至包括原 型鏈上的鍵。
  • 某些情況下, for … in 迴圈會以任意順序遍歷鍵名

總之, for . .. in 迴圈主要是為遍歷物件而設計的,不適用於遍歷陣列。

for … of 迴圈相比上面幾種做法有一些顯著的優點。

  • 有著同 for … in 一樣的簡潔語法,但是沒有 for … in 那些缺點。
  • 不同於 forEach 方法 , 它可以與 break 、 continue 和 return 配合使用 。
  • 提供了遍歷所有資料結構的統一操作介面。

相關文章