这真是毅种循环数组
Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制
,是一个用来访问某个对象的接口规范,为各类不一样的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就能够完成遍历操做
(即依次处理该数据结构的成员)。数据结构
Iterator的遍历某个数据结构过程是这样的(好比对array进行遍历)函数
建立一个指针对象,指向当前数组的起始位置
。也就是说,遍历器对象本质上,就是一个指针对象this
第一次调用指针对象的next方法
,能够将指针指向数据结构的第一个成员, 这时候的返回值是{value:array[0], done:false}指针
第二次调用指针对象的next方法
,指针就指向数据结构的第二个成员,这时候的返回值是{value:array[1], done:false}code
不断调用指针对象的next方法
,直到它指向数据结构的结束位置这时候的返回值是{value:array[array.length-1], done:true}对象
遍历完毕接口
为数组['a','b']手动写一个iterator接口内存
var itertaor = makeIterator(['a', 'b']); iterator.next() // { value: "a", done: false } iterator.next() // { value: "b", done: false } iterator.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}; } }; }
function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true}; } }; }
等价于:部署
let iterator = makeIterator(['a','b'])= {next:function(){xxxx}}
等价于:
iterator.next() = nextIndex<array.length ?{value: array[nextIndex++], done: false} :{value: undefined, done: true};
因此当 var iterator = makeIterator(['a','b'])
执行完,这时候makeIterator函数内部的nextIndex=0
, 但因为makeIterator
给外部变量iterator
返回了一个引用{next:function(){xxx}}
,因此makeIterator函数没法关闭,如今处于内存泄漏状态(函数的执行上下文环境没有关闭啊我摔!),
执行完第一个iterator.next()的时候, 因为此时nextIndex=0, nextIndex<array.length成立,返回的是{value: array[nextIndex++], done: false}
,这一句实际等价于: 返回{value: array[nextIndex], done: false}
而后nextIndex=nextIndex+1
,如今nextIndex=1了
执行完第二个iterator.next()的时候, 因为此时nextIndex=1, nextIndex<array.length成立,返回的是{value: array[nextIndex++], done: false}
,这一句实际等价于: 返回{value: array[nextIndex], done: false}
而后nextIndex=nextIndex+1
,如今nextIndex=2了
执行完第三个iterator.next()的时候, 因为此时nextIndex=2, nextIndex<array.length不成立,返回的是{value: undefined, done: true}
事实上,咱们不须要手动写array/set/map
的Iterator接口了,由于ES6规定它们是可遍历对象
,因此对应的Iterator接口已经被添加到对应的Symbol.iterator
属性上了(因此这三种数据结构才能用keys(for..of)/values(for..of)/entries(for..of)/foreach
这种方法进行遍历),你能够经过以下方式来获取
let arr = ['a', 'b', 'c']; let arrIterator = `arr[Symbol.iterator]()` let set = new Set([1,2,3]); let setIterator = `set[Symbol.iterator]()` let map = new Map([x,1][y,2]); let mapIterator = `map[Symbol.iterator]()`
对于非可遍历对象,好比{a:1,b:2},ES6并无规定这种对象键值对为可遍历对象,因此用for..of是不能对它进行遍历的.若是要使一个对象变成可遍历的,须要手动添加Iterator规则接口到它的Symbol.iterator
属性上去,好比
let obj = { data: [ 'hello', 'world' ], [Symbol.iterator]() { const self = this; let index = 0; return { next() { if (index < self.data.length) { return { value: self.data[index++], done: false }; } else { return { value: undefined, done: true }; } } }; } };
对于其余的不可遍历对象(好比类数组对象),你能够手动在Symbol.iterator
属性上部署上手写的Iterator接口(这样你本身能够写遍历规则),也可让Symbol.iterator
属性直接指向array的Iterator接口(这样就是用的数组的遍历规则)