- 迭代器
- 什么是迭代器?
- 迭代器的作用
- 生成器
- 介绍与应用
- 简单实现
[TOC]
## 迭代器
### 什么是迭代器?
迭代器(`iterator`)就是一个有`next`方法的对象,每次调用这个对象的next方法都会返回一个**新的对象**,这个新的对象有两个属性,分别是value和done(标识是否已迭代完毕)。
### 迭代器的作用
在使用`...`语法时,我们能将一个数组展开,像这样
```
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr = [...arr1,arr2];
<<<
[1,2,3,4,5,6]
```
可以发现arr1和arr2都被展开了放在一个数组中。
那么对象能不能像这样展开呢?
```
let obj = {0:1,1:2,2:3,length:3}
console.log([...obj])
<<<TypeError: obj is not iterable
```
我们会发现,它报了一个错误,obj is not iterable,对象是不可迭代的,
嗯。。我们知道数组也是一个对象,但它为什么可以而普通的对象就不行呢?
这就是因为数组对象里有`iterator`,而普通对象里没有,假若我们按照我们之前对迭代器的描述,手动在obj中添加一个
```
et obj = {0:1,1:2,2:3,length:3,[Symbol.iterator]:function(){
//内部会自动执行下面 每次调用next 通过done来决定是否停止
let index = 0; //当前迭代到了第几个
let self = this; //this指代的是当前对象
return {
next:function(){ // value代表的是当前的内容 done代表的是是否迭代完成
return {value:self[index],done:index++ === self.length?true:false}
}
}
}}
```
我们再试着展开
```
console.log([...obj]);
<<<
[1,2,3]
```
发现确实展开了
这,就是迭代器`iterator`的作用了。
## 生成器
### 介绍与应用
生成生成,就是要生点什么,那么`生成器`生了点什么呢?生成器实际上生成了`迭代器`。
嗯,可能这么解释还是不怎么清楚。其实生成器它本身是一个函数,或则说是一个集成的函数,它用`*`来标识它自己,像这样`function *gen(){}`,然后我们每次调用迭代器的next方法的时候,生成器方法就会被执行一部分,只有我们通过不断调用next,这个生成器方法才会被彻底执行完成,并在最后一次next调用时返回done:false的标识。
我们来看一个示例
```
function *r(){
let content1 = yield read('./1.txt','utf8');
let content2 = yield read(content1,'utf8');
return content2;
}
let it = r();
```
其中`*r`就是一个生成器函数,而`it`就是这个生成器函数生成的迭代器。每一次`it.next()`,生成函数都会执行一部分
![](https://user-gold-cdn.xitu.io/2018/3/25/1625b30dd5293820?w=397&h=137&f=png&s=27038)
其中青色的线框住的部分就是第一次调用`it.next`时执行的代码,橘色的是第二次,红色的是第三次。
也就是说每次调用时以`yield`为分界的,yield代表产出,它会以yield后面的部分作为`next`调用时返回的value值。
另外还有点需要注意的是生成器里的yield左边的`=`**并不**代表赋值运算,而代表调用`next`时会接受一个参数传入作为输入,**而content1、content2实际上是作为参数传入的形参。**
>[warning] **注意:** 第一次迭代是无法传入参数的,但生成器生成迭代器时可以接收参数作为输入。
最后生成器方法的return的值就是最后一次`next`调用时返回的value值,并且此时的done为true。(只有当生成器方法设置了return,才会存中所谓的最后一次next迭代,才会返回true)
### 简单实现
实现原理很简单就是利用闭包
```
function gen() {
let index = 0
, doneValue = false;
return function () {
if(++index === 3)doneValue=true;
if (index === 1) {
let V = '1';
return { value: V, done: doneValue }
}
if (index === 2) {
let V = '2';
return { value: V, done: doneValue }
}
if (index === 3) {
let V = '3';
return { value: V, done: doneValue }
}
}
}
let it = gen();
let o1 = it();
console.log(o1);
let o2 = it();
console.log(o2);
let o3 = it();
console.log(o3);
<<<
{ value: '1', done: false }
{ value: '2', done: false }
{ value: '3', done: true }
```
如果我们用babel编译原生的生成器实现的话,会发现内部其实用的是switch,嘛和if差不多。
---
---未完待续---