Generator生成器函数
生成器对象是由一个generator function返回的,并且它符合可迭代协议和迭代器协议。
生成器函数就是用来生成迭代器的。
如何创建一个生成器函数?
创建函数时,在function后加一个“星号 *”,则创建的函数为生成器函数
function* fn() {
console.log(this);
return 10;
}
- 把生成器函数 [fn] 执行,函数体中的代码并没有立即执行,而是而是创建了 [fn] 这个类的一个实例 [inst]
- inst.proto === fn.prototype
- inst这个对象,是符合迭代器规范的
- 有三个方法
- next
- return
- throw
- 有一些私有属性
- Symbol(Symbol.iterator)
- Symbol(Symbol.toStringTag): “Generator”
- …
- 有三个方法
普通函数VS生成器函数
- [把它当作一个实例__proto__]
- 普通函数是 Function 的实例,普通函数.proto===Function.prototype
- 生成器函数是 GeneratorFunction 的实例
- 生成器函数.proto===GeneraorFunction.prototype
- GeneratorFunction.prototype.proto===Function.prototype
- Object.toString.call(生成器函数) 结果是:"[object GeneratorFunction]"
- [把它作为一个构造函数 prototype]
- 生成器函数不能被new执行 Uncaught TypeError: func is not a constructor
- 当作普通函数执行,返回的结果就是生成器函数的一个实例
- inst.proto -> func.prototype「空对象,没有constructor」 -> Generator.prototype「constructor:GeneratorFunction」{next/return/throw/Symbol(Symbol.toStringTag): “Generator”} -> 一个具备迭代器规范的对象「Symbol(Symbol.iterator)」 -> Object.prototype
Generator.prototype.next()
next()方法返回一个包含 done 和 value 的对象,该方法也可以接收一个参数以向生成器传值
- 语法:
gen.next(value)
- 参数:value 向生成器传递的值
- 返回值:
function* generator() { console.log('A'); yield 10; console.log('B'); yield 20; console.log('C'); yield 30; console.log('D'); return 40; } let inst = generator(); // 每一次执行next,遇到yeild则结束;yeild后面的值,就是每一次返回对象中的value值; console.log(inst.next()); //输出‘A’ 结果{value:10,done:false} console.log(inst.next()); //输出‘B’ 结果{value:20,done:false} console.log(inst.next()); //输出‘C’ 结果{value:30,done:false} console.log(inst.next()); //输出‘D’ 结果{value:40,done:true} console.log(inst.next()); //结果{value:undefined,done:true}
- next方法给生成器传值
- 每一次执行next传递进来的值,是给上一个yeild的返回值赋值
- 第一次调用next方法,传参没有意义
function* generator() { let x1 = yield 10; console.log(x1); let x2 = yield 20; console.log(x2); return 30; } let itor = generator(); // 每一次执行next传递进来的值,是给上一个yeild的返回值赋值「第一次执行next传递进来的值是没用的」 console.log(itor.next('AA')); //没有输出 {value:10,done:false} console.log(itor.next('BB')); //输出“BB” {value:20,done:false} console.log(itor.next('CC')); //输出“CC” {value:30,done:true} console.log(itor.next('DD')); //{value:undefined,done:true}
- 如果再一个生成器中加入另外一个生成器,则迭代的时候会进入新的生成器中迭代
function* generator1() { yield 10; yield 20; } function* generator2() { yield 30; yield* generator1(); yield 40; } let itor = generator2(); console.log(itor.next()); //value:30 console.log(itor.next()); //value:10 加了yield*,则进入新的generator中迭代 console.log(itor.next()); //value:20 console.log(itor.next()); //value:40
Generator.prototype.return()
- 语法:
gen.return(value)
- 参数:value 需要返回的值
- 返回值:返回该函数参数中给定的值
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 }
Generator.prototype.throw()
- 语法:
gen.throw(exception)
- 参数:exception 用于抛出的异常。 使用 Error 的实例对调试非常有帮助
- 返回值:
function* gen() { while(true) { try { yield 42; } catch(e) { console.log("Error caught!"); } } } var g = gen(); g.next(); // { value: 42, done: false } g.throw(new Error("Something went wrong")); // "Error caught!"