Generator 函数的语法和应用
Generator 函数的语法和应用
  基本概念
    Generator 函数是 ES6 提供的一种异步编程解决方案，语法行为与传统函数完全不同
    Generator 函数有多种理解角度
      语法上，首先可以把它理解成，Generator 函数是一个状态机，封装了多个内部状态
        执行 Generator 函数会返回一个遍历器对象，也就是说，Generator 函数除了状态机，还是一个遍历器对象生成函数。返回的遍历器对象，可以依次遍历 Generator 函数内部的每一个状态。
      形式上，Generator 函数是一个普通函数，但是有两个特征
        一是，function关键字与函数名之间有一个星号
        二是，函数体内部使用yield表达式，定义不同的内部状态（yield在英语里的意思就是“产出”）
        Generator 函数的调用方法与普通函数一样。不同的是，调用 Generator 函数后，该函数并不执行，返回的也不是函数运行结果，而是一个指向内部状态的指针对象
        必须调用遍历器对象的next方法，使得指针移向下一个状态
    调用 Generator 函数，返回一个遍历器对象，代表 Generator 函数的内部指针。以后，每次调用遍历器对象的next方法，就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值，是yield表达式后面那个表达式的值；done属性是一个布尔值，表示是否遍历结束
  yield 表达式
    由于 Generator 函数返回的遍历器对象，只有调用next方法才会遍历下一个内部状态，所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志
    遍历器对象的next方法的运行逻辑如下
      （1）遇到yield表达式，就暂停执行后面的操作，并将紧跟在yield后面的那个表达式的值，作为返回的对象的value属性值。
      （2）下一次调用next方法时，再继续往下执行，直到遇到下一个yield表达式。
      （3）如果没有再遇到新的yield表达式，就一直运行到函数结束，直到return语句为止，并将return语句后面的表达式的值，作为返回的对象的value属性值。
      （4）如果该函数没有return语句，则返回的对象的value属性值为undefined。
    yield表达式与return语句既有相似之处，也有区别
      相似之处在于，都能返回紧跟在语句后面的那个表达式的值
      区别在于每次遇到yield，函数暂停执行，下一次再从该位置继续向后执行
    Generator 函数可以不用yield表达式，这时就变成了一个单纯的暂缓执行函数
    yield表达式只能用在 Generator 函数里面
    yield表达式如果用在 Generator 函数的另一个表达式之中，必须放在圆括号里面
  与 Iterator 接口的关系
    由于 Generator 函数就是遍历器生成函数，因此可以把 Generator 赋值给对象的Symbol.iterator属性，从而使得该对象具有 Iterator 接口
  next 方法的参数
    yield表达式本身没有返回值，或者说总是返回undefined。next方法可以带一个参数，该参数就会被当作上一个yield表达式的返回值
  for...of 循环
    for...of循环可以自动遍历 Generator 函数运行时生成的Iterator对象，且此时不再需要调用next方法
    除了for...of循环以外，扩展运算符（...）、解构赋值和Array.from方法内部调用的，都是遍历器接口。这意味着，它们都可以将 Generator 函数返回的 Iterator 对象，作为参数
  Generator.prototype.throw()
    Generator 函数返回的遍历器对象，都有一个throw方法，可以在函数体外抛出错误，然后在 Generator 函数体内捕获
  Generator.prototype.return()
    可以返回给定的值，并且终结遍历 Generator 函数
  next()、throw()、return() 的共同点
    它们的作用都是让 Generator 函数恢复执行，并且使用不同的语句替换yield表达式
      next()是将yield表达式替换成一个值。
      throw()是将yield表达式替换成一个throw语句
      return()是将yield表达式替换成一个return语句
  作为对象属性的 Generator 函数
  Generator 函数的this
    Generator 函数总是返回一个遍历器，ES6 规定这个遍历器是 Generator 函数的实例，也继承了 Generator 函数的prototype对象上的方法
  含义
    Generator 与状态机
    Generator 与协程
    Generator 与上下文
  异步应用
    传统方法
    基本概念
    Generator 函数
    Thunk 函数
    co 模块
  let obj = {
* myGeneratorMethod() {
···
}
};相当于let obj = {
myGeneratorMethod: function* () {
// ···
}
};
  function* numbers () {
yield 1
yield 2
return 3
yield 4
}
// 扩展运算符
[...numbers()] // [1, 2]
// Array.from 方法
Array.from(numbers()) // [1, 2]
// 解构赋值
let [x, y] = numbers();
x // 1
y // 2
// for...of 循环
for (let n of numbers()) {
console.log(n)
}
// 1
// 2
  var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
  function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next() // { value: 1, done: false }
g.return('foo') // { value: "foo", done: true }
g.next() // { value: undefined, done: true }