生成器
生成器是 ECMAScript 6 新增的一个极为灵活的结构,拥有在一个函数块内暂停和恢复代码执行的能力。
生成器基础
生成器的形式是一个函数,函数名称前面加一个星号表示它是一个生成器。
javascript//生成器函数声明 function* generatorFn(){} //生成器函数表达式 let generatorFn = function* () {} //作为对象字面量方法的生成器函数 let generator = { * generatorFn() {} } //作为类实例方法的生成器函数 class generator { * generatorFn() {} } //最为类静态方法的生成器函数 class generator { static * generatorFn() {} } //箭头函数不能用来定义生成器函数
生成器也具有next()方法,有一个done属性和一个value属性。
函数体为空的生成器函数中间不会停留,调用一次next()就会让生成器到达done:true状态。
javascriptfunction* generatorFn() {} let generatorObject = generatorFn(); console.log(generatorObject); // generatorFn {<suspended>} console.log(generatorObject.next()); // { done: true, value: undefined }
value属性是生成器的返回值,默认为undefined,可以通过生成器函数的返回值指定
javascriptfunction* generatorFn(){ return 'foo'; } let generatorObject = generatorFn(); console.log(generatorObject); // generatorFn {<suspended>} console.log(generatorObject.next()); // { done: true, value: 'foo' }
生成器的中断与执行
yield关键字可以让生成器停止和开始执行。停止执行的生成器函数只能通过在生成器对象上调用next()方法来恢复执行。
javascriptfunction* generatorFn() { yield; } let generatorObject = generatorFn(); console.log(generatorObject.next()); // { done: false, value: undefined } console.log(generatorObject.next()); // { done: true, value: undefined }
yield和return类似,但是yield关键字退出的生成器函数会处在done:false状态,return是true状态。
javascriptfunction* generatorFn() { yield 'foo'; yield 'bar'; return 'baz'; } let generatorObject = generatorFn(); console.log(generatorObject.next()); // { done: false, value: 'foo' } console.log(generatorObject.next()); // { done: false, value: 'bar' } console.log(generatorObject.next()); // { done: true, value: 'baz' }
throw()和return()方法都可以用于强制生成器进入关闭状态。
javascriptfunction* generatorFn() {} const g = generatorFn(); console.log(g); // generatorFn {<suspended>} console.log(g.next); // f next() { [native code] } console.log(g.return); // f return() { [native code] } console.log(g.throw); // f throw() { [native code] }
return()方法会强制生成器进入关闭状态。提供给return方法的值就是终止迭代器对象的值
javascriptfunction* generatorFn() { for (const x of [1, 2, 3]) { yield x; } } const g = generatorFn(); console.log(g); // generatorFn {<suspended>} console.log(g.return(4)); // { done: true, value: 4 } console.log(g); // generatorFn {<closed>}
throw()方法会在暂停的时候将一个提供的错误注入到生成器对象中。如果错误未被处理,生成器就会关闭
javascriptfunction* generatorFn() { for (const x of [1, 2, 3]) { yield x; } } const g = generatorFn(); console.log(g); // generatorFn {<suspended>} try { g.throw('foo'); } catch (e) { console.log(e); // foo } console.log(g); // generatorFn {<closed>}
如果生成器函数内部处理了这个错误,那么生成器就不会关闭,还可以恢复执行。错误处理会跳过对应的yield。
javascriptfunction* generatorFn() { for (const x of [1, 2, 3]) { try { yield x; } catch(e) {} } } const g = generatorFn(); console.log(g.next()); // { done: false, value: 1} g.throw('foo'); console.log(g.next()); // { done: false, value: 3}
如果生成器对象还没有开始执行,那么调用 throw()抛出的错误不会在函数内部被捕获,因为这相当于在函数块外部抛出了错误。