迭代器就是为了实现对不同集合进行统一遍历操作的一种机制。它本身就是实现了一套迭代协议。 迭代协议:规定了迭代与实现的逻辑。
可能很多同学看着字面的意思还是很迷惑,啥玩意?别着急,咱们一步步的撸下去。
2.1 针对数组的for-in 循环
回顾下for-in 这里直接上代码了;
let arr = ['a','b','c','d'] for(let attr in arr){ console.log(attr) }
这里面我们可以看出来输出的是key的值,也就是数组的下标;
2.2 针对数组的for of循环
let arr = ['a', 'b', 'c', 'd'] for (let val of arr) { console.log(val) }
通过for of 我们可以看到输出的是对应的value的值。
2.3 针对对象的for in和for of循环。
let obj = { a: 'a', b: 'b', c: 'c' } for (let attr in obj) { console.log(attr, '这是for in循环对象') } for (let val of obj) { console.log(val, '这是for of循环对象') }
此时我们可以看到for in循环对象没问题,但是for of的时候报错,提示这个对象obj是不可迭代的。我们分别在控制台输出arr和obj分别看下,我们可以发现arr有Symbol.iterator方法,但是obj没有。
我们要实现一个可迭代对象,只需要给它实现【Symbol.iterator】方法,而迭代器的实现过程就是迭代协议。下面我们就来手撸一个迭代器。
let obi = { a: 1, b: 2, c: 3 }; obj[Symbol.iterator] = function(){ return {} } for(let val of obj){ }此时我们运行下看看结果如何;
此时我们会发现这个对象缺少一个function。写迭代器一定要有一个next()方法,在next()里面必须有返回值;
let obj = { a: 1, b: 2, c: 3 }; obj[Symbol.iterator] = function(){ return { next(){ return { done: false //done表示迭代是否完成 fasle 代表否 } } } } for(let val of obj){ }此时在运行下,发现没有报错了,但是一直在执行,进入了一个死循环,舒服了。
下面我们来定义下规则,也就是迭代协议,就是你需要让它根据什么循环,就让它根据你的规定来循环。
let obj = { a: 1, b: 2, c: 3 }; obj[Symbol.iterator] = function(){ // 迭代协议 let values = Object.values(obj) let index = 0; console.log(values) return { next(){ if(index>= values.length){ //表示循环完成 return { // value: values[index++] 循环完成 done: true } }else{ return { done: false, value: values[index++] } } } } } for(let val of obj){ console.log(val) }此时执行就会发现,这个对象变成了可迭代对象。
我们可以模拟下它执行的过程。这里的代码我稍微修改下,为了测试它的执行过程;
let obj = { a: 1, b: 2, c: 3 }; obj[Symbol.iterator] = function(){ // 迭代协议 let values = Object.values(obj) let index = 0; return { next(){ if(index>= values.length){ //表示循环完成 return { // value: values[index++] 循环完成 done: true } }else{ return { done: false, value: values[index++] } } } } } let values = obj[Symbol.iterator](); console.log(values.next()) console.log(values.next()) console.log(values.next()) console.log(values.next()) // for(let val of obj){ // console.log(val) // }执行的结果:
到这我们就算实现了一个迭代器,for of就是相当于一直帮我们next()来执行这个迭代器。其中的迭代协议使我们自己定义的,现在只能输出value的值,那么我们可以让它同时输出key 和valule吗? 当然可以。
let obj = { a: 1, b: 2, c: 3 }; obj[Symbol.iterator] = function(){ // 迭代协议 let keys = Object.keys(obj) let index = 0; return { next(){ if(index>= keys.length){ //表示循环完成 return { // value: keys[index++] 循环完成 done: true } }else{ return { done: false, value: { key: keys[index], value: obj[keys[index++]] //++是为了方便next时拿到下一项 } } } } } } let values = obj[Symbol.iterator](); for(let val of obj){ console.log(val) }输出一下看看效果:
到这里,咱们的迭代器已经实现了,主要就是通过迭代协议来给对象封装一个Symbol.iterator方法,从而实现对象迭代的效果。下一篇我们将通过generator函数来实现封装一个async await异步执行方法。
