基本介绍
Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
function关键字与函数名之间有一个星号,函数体内部使用yield表达式,定义不同的内部状态。
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; }var hw = helloWorldGenerator();console.log(hw.next()) // { value: 'hello', done: false }console.log(hw.next()) // { value: 'world', done: false }console.log(hw.next()) // { value: 'ending', done: true }console.log(hw.next()) // { value: undefined, done: true }// value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
yield 表达式
yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
yield表达式如果用在另一个表达式之中,必须放在圆括号里面。
如果yield表达式后面跟的是一个遍历器对象,需要在yield表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*表达式。
function* foo() { yield 'a'; yield 'b'; }function* bar() { yield 'x'; yield* foo(); yield 'y'; }for (let v of bar()) { console.log(v); }// x a b y
遍历器对象的方法
next()
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。
function* foo(x) { var y = 2 * (yield(x + 1)); var z = yield(y / 3); return (x + y + z); }var a = foo(5);console.log(a.next()) //{ value: 6, done: false }console.log(a.next()) //{ value: NaN, done: false }console.log(a.next()) //{ value: NaN, done: true }var b = foo(5);console.log(b.next()) //{ value: 6, done: false }console.log(b.next(3)) // { value: 2, done: false }console.log(b.next(5)) // { value: 16, done: true } x=5 y=6 z=5
throw()
Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获。
throw方法可以接受一个参数,该参数会被catch语句接收,建议抛出Error对象的实例。
throw方法被捕获以后,会附带执行下一条yield表达式。也就是说,会附带执行一次next方法。
一旦 Generator 执行过程中抛出错误,且没有被内部捕获,就不会再执行下去了。
function* g() { try { yield; } catch (e) { console.log('内部捕获', e); } yield console.log('b'); };var i = g(); i.next(); i.throw(new Error('出错了!')); //内部捕获 Error: 出错了! b
return()
可以返回给定的值,并且终结遍历 Generator 函数。
如果 Generator 函数内部有try...finally代码块,那么return方法会推迟到finally代码块执行完再执行。
function* gen() { yield 1; yield 2; yield 3; }var g = gen();console.log(g.next()) // { value: 1, done: false }console.log(g.return('foo')) //{ value: 'foo', done: true }console.log(g.next()) //{ value: undefined, done: true }
Generator 函数的this
Generator 函数返回的总是遍历器对象,而不是this对象。
Generator 函数也不能跟new命令一起用,会报错。
function* g() { this.a = 11; }let obj = g();console.log(obj.a) //undefined
作者:tiancai啊呆
链接:https://www.jianshu.com/p/06d1997595a0