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 屬性是一個
布爾值,表示是否遍歷結束
作用
- 為各種數據結構提供一個統一 的、簡便的訪問接口;
- 使得 數據結構的成員能夠按某種次序排列;
- ES6 創造了 一種新的遍歷命令一for . . . of 循環, Iterator 接口 主要供 for ... of 消費。
過程
- 創建一個指針對象,指向當前數據結構的起始位置 。 也就是說,遍歷器對象本質上就是 一個指針對象 。
- 第一次調用指針對象的 next 方法,可以將指針指向數據結構的第 一個成員 。
- 第二次調用指針對象的 next 方法,指針就指向數據結構的第二個成員 。
- 不斷調用指針對象的 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 配合使用 。
- 提供了遍歷所有數據結構的統一操作接口。