ES6的Iterator遍历器
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