当前位置: 首页 > Web前端 > HTML

快速浏览ES6的生成器

时间:2023-03-28 11:36:08 HTML

生成器是添加到ECMAScript6中的一种极其灵活的结构,具有在功能块内暂停和恢复代码执行的能力。生成器函数提供了一个强大的替代方案:它们允许您定义一个包含自己的迭代算法的函数,同时自动维护自己的状态。生成器函数使用function*语法定义,*不受两边空格的影响。可以在任何可以定义函数的地方定义生成器。function*generator1(){}注意:箭头函数不能用来定义生成器函数。对生成器函数的方法调用会产生一个符合可迭代和迭代器协议的生成器对象。生成器对象最初暂停执行。与迭代器一样,生成器也实现了Iterator接口。Generator.prototype.next()Generator对象有一个next()方法,调用这个方法会导致generator开始或恢复执行,并返回一个带有done属性和value属性的IteratorResult对象。默认情况下,返回值为{done:true,value:undefined}。function*generator(){return'sample';}constv1=generator();//默认迭代器是自引用console.log(v1);//生成器{}console.log(generator()[Symbol.iterator]());//生成器{}console.log(v1.next());//{value:'sample',done:true}生成器内部也可以通过next(value)方法传递参数,这个参数会成为yield的结果。function*generator(){letv=yield10;yieldv;}letv=generator();console.log(v.next(1));//{值:10,完成:假}console.log(v.next(2));//{value:2,done:false}第一次调用next()时传入的值不会被使用,因为这次为了开始执行生成器函数,会执行并返回第一次yield的结果10.第二个next()调用,得到2作为结果让v=2并返回yieldv。Generator.prototype.return()Generator提供的return()方法返回给定的值并结束生成器。因此可以使用return()方法提前终止生成器。function*generator(){yield'sample';屈服;产生“例子”;返回'??实例';}constv1=generator();console.log(v1);//生成器{}console.log(v1.return("quit"));//{done:true,value:"quit"}console.log(v1);//generator{}在return()方法没有提供参数时返回一个对象value的value属性是undefined。当使用return()方法关闭生成器时,它无法恢复,后续调用next()方法返回值{done:true,value:undefined}。console.log(v1.next());//内置语言结构,例如{done:true,value:undefined}for-of循??环忽略状态为done:true的IteratorObject内部返回的值。function*generator(){yield'sample';屈服;产生“例子”;return'instance';}letv1=generator1();for(constxofv1){if(x==='example'){v1.return("quit");}console.log(x);}//sample//undefined//exampleGenerator.prototype.throw()生成器也提供了throw()方法来注入错误。如果错误未在内部处理,生成器将关闭。function*generator(){yield'sample';屈服;产生“例子”;返回'??实例';}constv=generator();console.log(v);////生成器{}try{v.throw(newError("ThrowError"));}catch(e){console.log(e);//错误:抛出错误}console.log(v);//generator{}但如果错误由生成器函数在内部处理,则生成器不会关闭并且可以恢复执行。错误处理会跳过相应的收益,因此在这种情况下会跳过一个值。如下:function*generator1(){for(constxof["sample","example","instance"]){try{yieldx;}catch(e){console.log("错误捕获!");}}}constv=generator();console.log(v.next());//{value:"sample",done:false}v.throw(newError("ThrowError"));//控制台日志(v);//生成器{}console.log(v.next);//{value:"instance",done:false}在这里,一个错误被注入到生成器中,该错误由yield关键字抛出,并在生成器内部的try-catch块中处理。此时生成器函数会继续执行,但是下次调用next()方法时,生成的不是实例值,而是实例值。注意:如果生成器对象还没有开始执行,调用throw()抛出的错误将不会被捕获到函数内部,因为这相当于在函数块外抛出错误。yieldECMAScript6提供了yield关键字来暂停生成器函数,并保留函数作用域的状态。生成器对象将通过调用next()方法恢复生成器函数的执行。yield省略表达式将返回未定义:function*generator(){yield'sample';屈服;产生“例子”;return'instance';}letv1=generator();console.log(v1.next());//{value:'sample',done:false}console.log(v1.next());//{值:未定义,完成:假}console.log(v1.next());//{value:'example',done:false}console.log(v1.next());//{value:'instance',done:true}console.log(v1.next());//{value:undefined,done:true}生成器对象可以看做是一个可迭代对象,可以使用for...of循环。function*generator(){for(constxof["sample","example","instance"]){yieldx;}}for(constxofgenerator1()){console.log(x);}//sample//example//instance注意:yield关键字只能在生成器函数内部使用,必须位于生成器函数中定义,如果它出现在嵌套的非生成器函数中,将抛出错误。yield的行为也可以使用yield*语法来增强,以委托给另一个生成器或可迭代对象。function*generator(){for(constvof[1,2,3]){yieldv;}}等价于function*generator(){yield*[1,2,3];}等价于function*generator1(){yield1;产量2;}function*generator2(){yield*generator1();yield3;}请注意,yield和*周围的空格不会影响其行为。由于yield*可以调用另一个生成器,因此可以通过yield*实现递归调用。函数*recs(n){if(n>1){yield*f(n-1);}yieldn;}for(constxofrecs(3)){控制台。log(x);}//1//2//3可以使用递归生成器结构和yield*优雅地表达递归算法。总结生成器是一个特殊的函数,它在被调用时返回一个生成器对象。Generator对象实现了Iterable接口,所以应用场景和iterator一样。生成器支持yield关键字,用于暂停生成器函数的执行,与next()方法配合使用,产生一系列的值。yield*表达式可以在生成器中调用其他生成器。更多内容请关注公众号《海人的故事》