一、Iterator
Iterator
(遍历器)为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署了该接口就可以使用 for of
遍历。
它的遍历过程是:
- 创建一个指针,指向当前数据结构的起始位置;
- 第一次调用指针的
next()
时,指针会指向数据结构的第一个成员,不断调用直到结束。
每次调用后,返回{value done}
两个属性的对象,value当前值,done表示遍历是否结束。
Iterator接口部署在Symbol.iterator
属性上,一个数据结构只要具有该属性,就认为是可遍历的
。
typeof obj[Symbol.iterator] === 'function'
原生具备 Iterator 接口的数据结构:
- 数组、字符串、伪数组对象
- Map、Set
- NodeList对象
二、Generator
在 js 中,一个函数一旦开始执行,就会运行到最后或遇到return结束,运行期间不会有其它代码能够打断它,也不能从外部再传入值到函数体内。而Generator
函数(生成器)的出现使得打破函数的完整运行成为了可能。
Generator
函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权,可以暂停执行和恢复执行。
1. 语法
Generator 函数的特征:(1)星号 *
(2)内部使用 yield
(用在普通函数报错)。
调用 Generator 函数,并不会执行该函数,而是返回一个迭代器对象Iterator,代表Generator函数内部的指针。然后只要调用迭代器的 next
方法,指针就会移到下一个 yield 或 return,并执行返回一个含有 value、done 两个属性的对象,
Generator 函数是分段执行的,yield 暂停执行,next 恢复执行。
function* fn() {
yield 'hello';
yield 'world';
return 'finished';
}
let g = fn(); // 普通调用
g.next(); // { value: 'hello', done: false }
g.next(); // { value: 'world', done: false }
g.next(); // { value: 'finished', done: true }
g.next(); // { value: undefined, done: true }
注意:Genarator 和 async/await 都可以用 try...catch
。
2. yield 和 return 区别
- 每次遇到 yield 就暂停执行,下一次再继续从该位置向后执行;而 return 不具备记忆位置的功能。
- 一个函数只能执行一次return
3. 协程
协程的运行流程为:
- 第1步,协程A开始执行
- 第2步,协程A执行到一半,进入暂停,执行权转移到协程B
- 第3步,协程B交还执行权
- 第4步,协程A恢复执行
yield 命令就将执行权交给其他协程,等待执行权返回。
4. 应用场景
- 协程操作
- 将异步回调变成了同步代码
虽然Generator函数能够实现异步编程,但实际上我们很少用它来实现异步,因为ES7引入的 async 函数对Generator函数的流程又做了一层封装,使得异步方案使用更加方便。