主要想了解的是async函数,但牵扯太多,环环相扣,挨个说叭
Iterator
概念
遍历器是一种机制:可以遍历处理各种数据结构(Array,Set,Map等)。也可理解是一种接口:为各种不同数据结构提供统一的访问机制。任何数据结构只要部署iterator接口,就可以完成遍历操作。
作用:
- 为各种数据结构提供 统一、简便的访问接口
- 使数据结构的成员能够按照某种次序排列
- 创建了 for…of 循环
理解遍历器的执行过程
var it = makeIterator(['a','b'])it.next() // { value: "a", done: false}it.next() // { value: "b", done: false}it.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};}}}
- 创建一个指针对象,指向当前数据结构的起始位置,指针对象必返回next方法。第一次调用指针对象的next方法,指针指向数据结构的第一个成员。第二次调用next方法,指针指向数据结构的第二个成员。不断调用指针对象的next方法,直到指向数据结构的结束位置。
每一次调用next方法都会返回,数据结构当前的成员信息。value和done属性组成的对象:{ value : ‘xx’, done : false }
「可遍历的」
“可遍历的”指一种数据部署了interator接口,可直接使用for…of… 循环。
- 默认的Iterator部署在数据结构的Symbol.interator属性上。所以说,一个数据结构只要部署了Symbol.interator属性,就认为是「可遍历的」。
- Array
- Map
- Set
- String
- TypedArray
- 函数的arguments对象
- NodeList对象 ```javascript let arr = [‘a’, ‘b’, ‘c’]; let iter = arrSymbol.iterator; //⚠注意:此处属性后要加()
iter.next() // { value: ‘a’, done: false } iter.next() // { value: ‘b’, done: false } iter.next() // { value: ‘c’, done: false } iter.next() // { value: undefined, done: true }
<a name="e7MQz"></a>#### 使用场景结构赋值 、 扩展运算符、yield*、for...of... 、Array.from() 、Map()、Set()、Promise.all()、Promise.race()<a name="uBjAo"></a># Generator<a name="orD9V"></a>#### 概念**Generator函数 **ES6提供的 一种解决异步编程解决方案。可理解为是一个状态机,封装了多个内部状态。也是一个遍历器对象生成函数,会返回一个新的遍历器对象。```javascriptfunction* helloWorldGenerator() {yield 'hello';yield 'world';return 'ending';}var hw = helloWorldGenerator();
- Generator函数,function 关键字和函数名之间有一个星号*
- 函数体内部用yield表达式,来定义不同的内部状态。
- 调用Generator函数后,该函数并不会执行。如上函数的执行结果hw,是一个指向内部状态的指针对象,即遍历器对象
console.log(hw.next())console.log(hw.next())console.log(hw.next())console.log(hw.next())

调用 next() 方法,Generator函数开始执行。遇到第一个yield表达式,停止,返回当前yield表达式的值,以及是否结束的状态done。再调 next(), 再接着执行,再到下一个yield表达式,或return。
yield表达式
由于Generator函数返回的是遍历器对象,调用 next() 才会获得下一个内部状态,所以可理解为 yield表达式是暂停标志。
调用 next() 后的执行逻辑:
- 遇到yield表达式,就暂停后续操作。并将紧跟在yield后的表达式的值当作返回对象的value值。
- 下一次再调用 next() 方法时,继续往下执行,直到遇到下一个yield表达式。
- 如果没有遇到新的yield表达式,就一直运行到函数结束,直到 return 语句为止,并将return后的值当作返回对象的value值。
- 如果该函数没有 return语句,则返回对象的value值为undefined。
1、暂缓执行函数
yield表达式的值不会立即求值,只会在next方法将指针移到这一步才执行。
2、yield表达式只能用在Generator函数里面
用在普通股函数内会报错
3、yield表达式如果用在另一个表达式之中,必须放在圆括号里面。
function* demo() {console.log('Hello' + (yield)); // OKconsole.log('Hello' + (yield 123)); // OK}
next()参数
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
它的重要意义在于,Generator函数从暂停状态到开始运行,它的上下文状态是不变的,那通过next参数,就可以在Generator函数开始运行之后,继续向函数传进新的值,从而调整函数的值。
function* testNext(x){const y = yield x+6;const z = yield y*2;return (x+y+z)}const req = testNext(4)console.log(req.next())console.log(req.next(2))console.log(req.next(2))
与Interator接口的关系
1、由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.interator属性,从而使得该对象具有 Iterator 接口。
var myIterable = {};myIterable[Symbol.iterator] = function* () {yield 1;yield 2;yield 3;};[...myIterable] // [1, 2, 3]
2、Generator 函数执行后,返回一个遍历器对象。该对象本身也具有Symbol.interator属性,执行后返回自身。
function* gen(){}var g = gen();g[Symbol.iterator]() === g
3、for…of…
for…of循环可以自动遍历 Generator 函数运行时生成的Iterator对象,且此时不再需要调用next方法。
function* foo() {yield 1;yield 2;yield 3;yield 4;yield 5;return 6;}for (let v of foo()) {console.log(v);}// 1 2 3 4 5
一旦next方法的返回对象的done属性为true,for…of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for…of循环之中。
function* numbers () {yield 1yield 2return 3yield 4}// 扩展运算符[...numbers()] // [1, 2]// Array.from 方法Array.from(numbers()) // [1, 2]// 解构赋值let [x, y] = numbers();x // 1y // 2// for...of 循环for (let n of numbers()) {console.log(n)}// 1// 2
throw() 、return()、和next()
应用
1. 部署Iterator接口
利用Generator接口,可以为任何对象部署Iterator接口
function* objectEntries() {let propKeys = Object.keys(this);for (let propKey of propKeys) {yield [propKey, this[propKey]];}}let jane = { first: 'Jane', last: 'Doe' };jane[Symbol.iterator] = objectEntries;for (let [key, value] of jane) {console.log(`${key}: ${value}`);}
