ES6新特性三: Generator(生成器)函数详解
本文实例讲述了ES6新特性三:Generator(生成器)函数。分享给大家供大家参考,具体如下:
1.简介
①理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改变。
②写法:
function*f(){}
③作用:就是可以完全控制函数的内部状态的变化,依次遍历这些状态。
④运行过程:当调用Generator函数的时候,该函数并不执行,而是返回一个遍历器(可以理解成暂停执行)。通过调用next()开始执行,遇到yield停止执行,返回一个value属性值为当前yield语句的值,done属性为false的对象,循环调用next(),一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。
示例:
function*helloWorldGenerator(){ yield'hello'; yield'world'; return'ending'; } varhw=helloWorldGenerator();//第一次调用该方法不会执行,仅返回一个遍历器。 vara=hw.next(); while(!a.done){//当执行到return时,a.done=true,终止循环 console.log(a.value+','+a.done); a=hw.next(); } console.log(a.value+','+a.done);
结果:
hello,false world,false ending,true
2.next()的参数
①我们要知道是next()返回一个对象,yield语句本身是没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
function*f(){ for(vari=0;true;i++){ varreset=yieldi; console.log(reset);//打印reset,验证yield语句是没有返回值的 if(reset){i=-1;} } } varg=f(); console.log(g.next())//{value:0,done:false} console.log(g.next())//{value:1,done:false} console.log(g.next(true))//{value:0,done:false}
结果:
{value:0,done:false} undefined {value:1,done:false} true {value:0,done:false}
通过next方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。也就是说,可以在Generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。
②由于next方法的参数表示上一个yield语句的返回值,所以第一次使用next方法时,不能带有参数。V8引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。
function*foo(x){ vary=2*(yield(x+1)); varz=yield(y/3); return(x+y+z); } varit=foo(5); console.log(it.next(3))//{value:6,done:false} console.log(it.next(12))//{value:8,done:false} console.log(it.next(13))//{value:42,done:true}
3.for-of遍历generator
for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法,
一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象
function*foo(){ yield1; yield2; yield3; yield4; yield5; return6; } for(letvoffoo()){ console.log(v); } //12345
4.yield*语句
①如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。
leta=(function*(){ yield'Hello!'; yield'Bye!'; }()); letb=(function*(){ yield'Greetings!'; yield*a; yield'Ok,bye.'; }()); for(letvalueofb){ console.log(value); }
结果:
Greetings! Hello! Bye! Ok,bye.
②yield命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器。
function*gen(){ yield*["a","b","c"]; } gen().next()//{value:"a",done:false}
遍历嵌套数组:
function*iterTree(tree){ if(Array.isArray(tree)){ for(leti=0;i希望本文所述对大家ECMAScript程序设计有所帮助。