- 迭代器
- 什么是迭代器?
- 迭代器的作用
- 生成器
- 介紹與應用
- 簡單實現
[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()`,生成函數都會執行一部分

其中青色的線框住的部分就是第一次調用`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差不多。
---
---未完待續---