遍历器(Iterator)是一种接口,为各类不一样的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就能够完成遍历操做(即依次处理该数据结构的全部成员)。es6
Iterator的做用有三个:一是为各类数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员可以按某种次序排列;三是ES6有一种新的遍历方式,for...of,而Iterator的主要做用,就是支持此操做。数组
在ES6中,有些数据结构原生具有Iterator接口(好比数组),即不用任何处理,就能够被for...of循环遍历,有些就不行(好比对象)。缘由在于,这些数据结构原生部署了Symbol.iterator属性(详见下文),另一些数据结构没有。数据结构
凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。函数
在ES6中,有三类数据结构原生具有Iterator接口:数组、某些相似数组的对象、Set和Map结构。它们三者不须要咱们手动部署Symbol.iterator属性就能够使用for...of遍历功能。而普通对象使用for...of遍历就会报错,由于它没有部署该接口。spa
若是你须要使本来不具有for...of遍历功能的集合具有该功能,就须要手动为它部署。ES6有许多内置的Symbol值,这些就是接口。prototype
下面咱们利用迭代器中的原理来给对象生成一个迭代器,实现让对象能够使用for...ofcode
var person={ name: 'zz', age: 18 }
//给person对象添加一个iterator接口
person[Symbol.iterator] = function(){
//使用object.keys()方法把j对象中的k值读取出来存在数组当中
var arr = Object.keys(person); var i = 0; return { //ES6中next()迭代方法,自动迭代
next(){ if(i < arr.length){ //若是done为false,继续迭代
return { //返回迭代的最后结果,若是是一个对象,那么for of的时候须要用解构
value: { k : arr[i], val: person[arr[i++]] }, done: false } }else{ //若是done为true,继续迭代
return { value: null, done : true } } } } }
//解构获取返回获得的对象,输出k值,val值
for(var {key,val} of person){ console.log(key,val); }
咱们能够看到:对象
一、经过为person对象部署Symbol.iterator接口,就使它实现了for...of 功能。blog
二、Symbol.iterator中返回一个对象,该对象包含一个next() 方法,定义了遍历功能。接口
三、next方法中的value和done,value是遍历过程当中返回的键值对信息,done是一个表示遍历是否结束的布尔值。
补充:
一、遍历器对象除了具备next方法,还能够具备return方法和throw方法。若是你本身写遍历器对象生成函数,那么next方法是必须部署的,return方法和throw方法是否部署是可选的。
当一个解构在遍历的时候异常提早退出(好比break,continue或者出错)的时候,就会调用return方法,其次,return方法必须返回一个对象。
至于throw方法,则是用于抛出错误,Generator.prototype.throw这里不展开讲了,感兴趣的能够搜索一下。
二、用ES6新功能Generator函数来实现Symbol.iterator接口,事半功倍。
var yieldIterator = {}; yieldIterator[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...yieldIterator] // [1, 2, 3]
注意,yield* 后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
对Generator不了解的能够戳 ES6 Generator的语法 ,这里很少说。
三、至于能够使用Array.from转换成数组的类数组对象,部署iterator有一种很简单的方法,即直接使用数组的[Symbol.iterator]接口。
fakeArray.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
一、解构赋值
二、扩展运算符(...)
三、上文提到的 yield*
四、因为数组的遍历会调用遍历器接口,因此任何接受数组做为参数的场合,都默认调用,如
for...of
Array.from()
Map(), Set(), WeakMap(), WeakSet()
Promise.all()
Promise.race()
五、字符串是一个相似数组的对象,原生也具备Iterator接口