JS表示集合的對象主要有Array、Set、Object、Map,在以前,遍歷它們需要使用2種不同的方法,而現在,JS提出了Iterator機制,可以給不同的數據結構提供統一的遍歷方法,就是for…of。換句話說,只有部署了Iterator的數據才能用for…of遍歷。
Iterator的遍歷過程是這樣的:
(1)創建一個指針對象,指向當前數據結構的起始位置。也就是說,遍歷器對象本質上,就是一個指針對象。
(2)第一次調用指針對象的next
方法,可以將指針指向數據結構的第一個成員。
(3)第二次調用指針對象的next
方法,指針就指向數據結構的第二個成員。
(4)不斷調用指針對象的next
方法,直到它指向數據結構的結束位置。
每一次調用next
方法,都會返回數據結構的當前成員的信息。具體來說,就是返回一個包含value
和done
兩個屬性的對象。其中,value
屬性是當前成員的值,done
屬性是一個布爾值,表示遍歷是否結束。
ES6 規定,默認的 Iterator 接口部署在數據結構的Symbol.iterator
屬性,或者說,一個數據結構只要具有Symbol.iterator
屬性,就可以認為是“可遍歷的”(iterable)。
默認部署了Iterator的數據有
-Array
-Map
-Set
-String
-arguments
-NodeList 對象
一個對象要被for…of遍歷,必須部署Iterator,或者在其原型上部署Iterator,普通對象並沒有部署Iterator,如果用for…of遍歷,會拋出“not iterable”錯誤
然而,一個類似於數組的普通對象直接調用數組的Symbol.iterator,也是可以用for…of遍歷的
let iterable = { 0: 'a', 1: 'b', 2: 'c', length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // 'a', 'b', 'c' }
需要注意的是,“類似於數組”這個條件,不僅僅要以數字為索引,length屬性也必不可少
兩個條件中,任何一條不滿足(就是普通對象),調用數組的Symbol.iterator是行不通的
那么普通對象到底要怎樣才能被for…of遍歷?
一是利用Object.keys得到對象的鍵名然后遍歷這個數組
for (var key of Object.keys(someObject)) { console.log(key + ': ' + someObject[key]); }
Iterator的遍歷過程看着像Generator,Generator可以很簡單就實現Iterator接口,所以第二種方法就是利用Generator方法將對象包裝一下
function* entries(obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]]; } } for (let [key, value] of entries(obj)) { console.log(key, '->', value); }
總結參考:http://es6.ruanyifeng.com/#docs/iterator