您好,登錄后才能下訂單哦!
本文實例講述了ES6 Iterator遍歷器原理,應用場景及相關常用知識拓展。分享給大家供大家參考,具體如下:
介紹Iterator之前先列舉下js的表示數據集合結構的幾種方式:
在es6之前有 Array , Object, es6新增了 map, set,當然用戶也可以組合使用這幾種數據結構,靈活存儲數據。
但是當數據結構變得復雜后,怎樣取到里面的數據就也相對復雜,這就需要有一種讀取數據的統一的接口機制,來處理不同的數據結構。
1,為各種數據結構提供一種統一的,簡單的訪問接口;
2,使得數據結構的成員能夠按照某種次序排列;
3,ES6提供了一種新的遍歷循環(for......of.....),Iterator被for......of.....循環調用;
遍歷器本質上是一種指針對象,指針對象上有next()方法,第幾次調用就指向第幾個成員
1,返回當前成員的信息
2,返回遍歷是否結束
模擬實現Iterator
var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true}; } }; }
使用Typescript
interface Iterable { [Symbol.iterator]() : Iterator, } interface Iterator { next(value?: any) : IterationResult, } interface IterationResult { value: any, done: boolean, }
ES6 規定,默認的 Iterator 接口部署在數據結構的Symbol.iterator
屬性,或者說,一個數據結構只要具有Symbol.iterator
屬性,就可以認為是“可遍歷的”(iterable)。
Symbol.iterator的本質:
1,Symbol.iterator本身是一個函數,對應當前數據結構默認的遍歷器生成函數;
2,執行Symbol.iterator這個函數會返回一個遍歷器。
實例:
const obj = { [Symbol.iterator] : function () { return { next: function () { return { value: 1, done: true }; } }; } }; //這樣定義后對象就有了Iterator接口 //執行對象obj的symbol.iterator后,返回一個遍歷器
具有原生iterator的數據結構:
Array , Map, Set, String, TypedArray, 函數的argulements對象,NodeList對象(節點對象);
數組iterator實例
let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false } iter.next() // { value: undefined, done: true }
對象iterator接口實現
class RangeIterator { constructor(start, stop) { this.value = start; this.stop = stop; } [Symbol.iterator]() { return this; } next() { var value = this.value; if (value < this.stop) { this.value++; return {done: false, value: value}; } return {done: true, value: undefined}; } } function range(start, stop) { return new RangeIterator(start, stop); } for (var value of range(0, 3)) { console.log(value); // 0, 1, 2 }
注意:如果一個對象沒有iterator接口,而其原型鏈上有Iterator接口,也可以通過繼承而擁有該接口;
使用while
循環遍歷
var $iterator = ITERABLE[Symbol.iterator](); var $result = $iterator.next(); while (!$result.done) { var x = $result.value; // ... $result = $iterator.next(); }
基本概念基本就是這些,接下來看下使用場景
默認調用場景:
for....of...循環, 解構賦值, 擴展運算符, yield*關鍵字
ES6 借鑒 C++、Java、C# 和 Python 語言,引入了for...of
循環,作為遍歷所有數據結構的統一的方法
這里主要介紹下yield*,其余幾個都比較好理解
yield*
后面跟的是一個可遍歷的結構,它會調用該結構的遍歷器接口
let generator = function* () { yield 1; yield* [2,3,4];//執行時默認遍歷數組 yield 5; }; var iterator = generator(); iterator.next() // { value: 1, done: false } iterator.next() // { value: 2, done: false } iterator.next() // { value: 3, done: false } iterator.next() // { value: 4, done: false } iterator.next() // { value: 5, done: false } iterator.next() // { value: undefined, done: true }
其他場景:
由于數組的遍歷會調用遍歷器接口,所以任何接受數組作為參數的場合,其實都調用了遍歷器接口
new Map([['a',1],['b',2]])
)知識拓展:
return方法在循環退出或者報錯時調用
throw
方法主要是配合 Generator 函數使用(詳見generator)
在原有數據結構基礎上計算生成的數據結構,例如Object,Map,Set,Array的entries(),keys(), value()方法生成的數據結構,默認具有iterator接口
常見:字符串,NodeList節點對象,參數arguments
1,并不是所有類似數組的對象都具有 Iterator 接口
2,對于類數組對象可以通過Array.From()將類數組對象轉化為數組對象
3,for-of可以識別32 位 UTF-16 字符
for (let x of 'a\uD83D\uDC0A') { console.log(x); }
for循環,forEach循環,for...in...循環
forEach循環無法中途跳出
for...in
循環有幾個缺點(for...in
循環主要是為遍歷對象而設計的,不適用于遍歷數組),
for...in
循環是以字符串作為鍵名“0”、“1”、“2”等等。for...in
循環不僅遍歷數字鍵名,還會遍歷手動添加的其他鍵,甚至包括原型鏈上的鍵。for...in
循環會以任意順序遍歷鍵名。對于for...of...
for...in
一樣的簡潔語法,但是沒有for...in
那些缺點。forEach
方法,它可以與break
、continue
和return
配合使用。參考:http://es6.ruanyifeng.com/
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼運行效果。
更多關于JavaScript相關內容可查看本站專題:《javascript面向對象入門教程》、《JavaScript錯誤與調試技巧總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。