迭代器是被設計專用於迭代的對象,帶有特定接口。全部的迭代器對象都擁有 next() 方
法,會返回一個結果對象。該結果對象有兩個屬性:對應下一個值的 value ,以及一個布爾
類型的 done ,其值爲 true 時表示沒有更多值可供使用。迭代器持有一個指向集合位置的
內部指針,每當調用了 next() 方法,迭代器就會返回相應的下一個值。
記住這些後,在 ES5 中建立一個迭代器就至關簡單了:數組
function ceateIterator(items) { var i = 0; return { next: function() { var done = (i >= items.length); var value = !done ? items[i++]: undefined; return { done: done, value: value }; } }; } var iterator = createIterator([1, 2, 3]); console.log(iterator.next()); // "{ value: 1, done: false }" console.log(iterator.next()); // "{ value: 2, done: false }" console.log(iterator.next()); // "{ value: 3, done: false }" console.log(iterator.next()); // "{ value: undefined, done: true }" // 以後的全部調用 console.log(iterator.next()); // "{ value: undefined, done: true }"
與迭代器緊密相關的是,可迭代對象( iterable )是包含 Symbol.iterator 屬性的對象。這
個 Symbol.iterator 知名符號定義了爲指定對象返回迭代器的函數。在 ES6 中,全部的集合
對象(數組、 Set 與 Map )以及字符串都是可迭代對象,所以它們都被指定了默認的迭代
器。可迭代對象被設計用於與 ES 新增的 for-of 循環配合使用。函數
for-of在循環每次執行時會調用可迭代對象next()方法,並將結果value值保存在一個變量上,循環過程到done變成true時中止。設計
let values = [1, 2, 3]; for (let num of values) { console.log(num); }
此代碼輸出以下指針
1 2 3
這個 for-of 循環首先調用了 values 數組的 Symbol.iterator 方法,獲取了一個迭代器
(對 Symbol.iterator 的調用發生在 JS 引擎後臺)。接下來 iterator.next() 被調用,迭
代器結果對象的 value 屬性被讀出並放入了 num 變量。 num 變量的值開始爲 1 ,接下來
是 2 ,最後變成 3 。當結果對象的 done 變成 true ,循環就退出了,所以 num 毫不會被
賦值爲 undefined 。code
你可使用 Symbol.iterator 來訪問對象上的默認迭代器,就像這樣:orm
let values = [1, 2, 3]; let iterator = values[Symbol.iterator](); console.log(iterator.next()); // "{ value: 1, done: false }" console.log(iterator.next()); // "{ value: 2, done: false }" console.log(iterator.next()); // "{ value: 3, done: false }" console.log(iterator.next()); // "{ value: undefined, done: true }"
既然 Symbol.iterator 指定了默認迭代器,你就可使用它來檢測一個對象是否能進行迭
代,正以下例:對象
function isIterable(object) { return typeof object[Symbol.iterator] === "function"; } console.log(isIterable([1, 2, 3])); // true console.log(isIterable("Hello")); // true console.log(isIterable(new Map())); // true console.log(isIterable(new Set())); // true console.log(isIterable(new WeakMap())); // false console.log(isIterable(new WeakSet())); // false
ES6 具備三種集合對象類型:數組、 Map 與 Set 。這三種類型都擁有以下的迭代器,有助於
探索它們的內容:索引
entries() 迭代器會在每次 next() 被調用時返回一個雙項數組,此數組表明了集合中每一個
元素的鍵與值:對於數組來講,第一項是數值索引;對於 Set ,第一項也是值(由於它的值
也會被視爲鍵);對於 Map ,第一項就就是鍵。接口
let colors = [ "red", "green", "blue" ]; let tracking = new Set([1234, 5678, 9012]); let data = new Map(); data.set("title", "Understanding ES6"); data.set("format", "ebook"); for (let entry of colors.entries()) { console.log(entry); } for (let entry of tracking.entries()) { console.log(entry); } for (let entry of data.entries()) { console.log(entry); }
輸出內容以下:字符串
[0, "red"] [1, "green"] [2, "blue"] [1234, 1234] [5678, 5678] [9012, 9012] ["title", "Understanding ES6"] ["format", "ebook"]
values() 迭代器僅僅能返回存儲在集合內的值,例如:
let colors = [ "red", "green", "blue" ]; let tracking = new Set([1234, 5678, 9012]); let data = new Map(); data.set("title", "Understanding ES6"); data.set("format", "ebook"); for (let value of colors.values()) { console.log(value); } for (let value of tracking.values()) { console.log(value); } for (let value of data.values()) { console.log(value); }
此代碼輸出了以下內容:
"red" "green" "blue" 1234 5678 9012 "Understanding ES6" "ebook"
keys() 迭代器能返回集合中的每個鍵。對於數組來講,它只返回了數值類型的鍵,永不返
回數組的其餘自有屬性; Set 的鍵與值是相同的,所以它的 keys() 與 values() 返回了相
同的迭代器;對於 Map , keys() 迭代器返回了每一個不重複的鍵。這裏有個例子演示了這三
種狀況:
let colors = [ "red", "green", "blue" ]; let tracking = new Set([1234, 5678, 9012]); let data = new Map(); data.set("title", "Understanding ES6"); data.set("format", "ebook"); for (let key of colors.keys()) { console.log(key); } for (let key of tracking.keys()) { console.log(key); } for (let key of data.keys()) { console.log(key); }
本例輸出了以下內容:
0 1 2 1234 5678 9012 "title" "format"