├── Generator
│ ├── 简介
│ │ └─ 基本概念
│ │ └─ Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
│ │ └─ 执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。
│ │ └─ Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是必须调用遍历器对象的 `next`方法,使得指针移向下一个状态。
│ │ └─ function * foo(x, y) { ··· } function *foo(x, y) { ··· } function* foo(x, y) { ··· } function*foo(x, y) { ··· } 写法均可
│ │ └─ yield 表达式
│ │ └─ `yield`表达式与`return`语句既有相似之处,也有区别。相似之处在于,都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到`yield`,函数暂停执行,下一次再从该位置继续向后执行,而`return`语句不具备位置记忆的功能。
│ │ └─ 正常函数只能返回一个值,因为只能执行一次`return`;Generator 函数可以返回一系列的值,因为可以有任意多个`yield`。
│ │ └─ 一个函数里面,只能执行一次(或者说一个)`return`语句,但是可以执行多次(或者说多个)`yield`表达式。
│ ├── for...of 循环
│ │ └─ `for...of`循环可以自动遍历 Generator 函数运行时生成的`Iterator`对象,且此时不再需要调用`next`方法。
│ │ └─ 除了`for...of`循环以外,扩展运算符(`...`)、解构赋值和`Array.from`方法内部调用的,都是遍历器接口。这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参
│ ├── Generator.prototype.throw()
│ │ └─ Generator 函数返回的遍历器对象,都有一个`throw`方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获。
│ │ └─ 遍历器对象`i`连续抛出两个错误。第一个错误被 Generator 函数体内的`catch`语句捕获。`i`第二次抛出错误,由于 Generator 函数内部的`catch`语句已经执行过了,不会再捕捉到这个错误了,所以这个错误就被抛出了 Generator 函数体,被函数体外的`catch`语句捕获。
│ │ └─ `throw`方法可以接受一个参数,该参数会被`catch`语句接收,建议抛出`Error`对象的实例。
│ │ └─ `throw`命令与`g.throw`方法是无关的,两者互不影响。 不要混淆遍历器对象的`throw`方法和全局的`throw`命令
│ │ └─ 如果 Generator 函数内部没有部署`try...catch`代码块,那么`throw`方法抛出的错误,将被外部`try...catch`代码块捕获。
│ │ └─ `throw`方法抛出的错误要被内部捕获,前提是必须至少执行过一次`next`方法。
│ │ └─ `throw`方法被捕获以后,自动执行了一次`next`方法
│ ├── Generator.prototype.return()
│ │ └─ Generator 函数返回的遍历器对象还有一个`return()`方法,可以返回给定的值,并且终结遍历 Generator 函数。
│ │ └─ Generator 函数返回的遍历器对象`g`调用`return()`方法后,返回值的`value`属性就是`return()`方法的参数`foo`. 并且,Generator 函数的遍历就终止了,返回值的`done`属性为`true`,以后再调用`next()`方法,`done`属性总是返回`true`。如果`return()`方法调用时,不提供参数,则返回值的`value`属性为`undefined`。
│ │ └─ Generator 函数内部有`try...finally`代码块,且正在执行`try`代码块,那么`return()`方法会导致立刻进入`finally`代码块,执行完以后,整个函数才会结束。
│ ├── next()、throw()、return() 的共同点
│ │ └─ 它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换`yield`表达式。
│ │ └─ `next()`是将`yield`表达式替换成一个值。
│ │ └─ `throw()`是将`yield`表达式替换成一个`throw`语句。
│ │ └─ `return()`是将`yield`表达式替换成一个`return`语句。
│ ├── yield* 表达式
│ │ └─ ES6 提供了`yield*`表达式,作为解决办法,用来在一个 Generator 函数里面执行另一个 Generator 函数。
│ │ └─ 如果`yield`表达式后面跟的是一个遍历器对象,需要在`yield`表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为`yield*`表达式。
│ │ └─ 如果`yield*`后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员。`yield`命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器对象。
│ ├── 作为对象属性的 Generator 函数
│ │ └─ 如果一个对象的属性是 Generator 函数,可以简写成下面的形式。let obj = { * myGeneratorMethod() { ··· } };
│ │ └─ 等同于 let obj = { myGeneratorMethod: function* () {