Generatoren - de knoestige stukjes

De conceptspecificatie van ECMAScript 6 heeft de moderne JavaScript-ontwikkelaar al veel vreugde opgeleverd. In een vorig bericht hebben we enkele nieuwe collectieklassen en for..of iteratielussen besproken. In dit bericht gaan we het hebben over iets dat hand in hand gaat met for..of loops: generatorfuncties.

Er is al heel veel geweldig materiaal beschikbaar over het waarom en hoe van het gebruik van generatoren. In een notendop zijn generatoren speciale functies die iterators creëren, en iterators zijn objecten die een next() methode hebben, die kan worden aangeroepen om een ​​waarde te verkrijgen. Binnen een generatorfunctie levert het trefwoord yield de waarde voor next() . Het gebruik yield schort de uitvoering van de generatorfunctie op, waarbij de status behouden blijft totdat next() opnieuw wordt aangeroepen, waarna de code weer opstart en doorgaat, totdat deze een andere waarde yield (of totdat de generatorfunctie eindigt). Er zijn verschillende canonieke gebruiksscenario's voor generatorfuncties, zoals het gebruik ervan om de getallen in de Fibonacci-reeks te herhalen.

Nu de basisbeginselen achter de rug zijn, gaan we dieper in op een JavaScript-voorbeeld dat enkele van de valkuilen, of “moeilijke stukjes”, van het werken met generatoren behandelt. Er zijn overal uitgebreide commentaren en je kunt spelen met de live versie van de code voordat je deze doorleest:

Dus wat zijn enkele belangrijke conclusies uit de code?

Ten eerste resulteert het construeren van een generator in een unieke iterator met zijn eigen specifieke status, en kunt u parameters doorgeven aan de generatorconstructor die het gedrag kan controleren.

Ten tweede kun je een parameter doorgeven bij het aanroepen van de next() methode van een iterator, en die waarde zal worden toegewezen aan wat zich aan de linkerkant van de yield instructie bevindt van de vorige iterator-aanroep. Dit is een goede manier om de uitvoer van de iterator te variëren; hier gebruiken we het om te bepalen of het resulterende woord in hoofdletters staat of niet. Als je de allereerste waarde die wordt opgeleverd wilt beïnvloeden, doe dat dan via een parameter naar de constructor van de generator.

Ten slotte kunnen generatoren eindige of oneindige iteratoren produceren. Als je met een oneindige iterator werkt, zorg er dan voor dat je een soort terminale voorwaarde hebt, gebaseerd op de waarde yield ed. Het is heel gemakkelijk om per ongeluk oneindige lussen te schrijven, vooral als je for..of gebruikt voor iteratie. Als u met een eindige iterator werkt via aanroepen van next() , geeft de eigenschap .done van het geretourneerde object aan of de iteratie voltooid is.

We hopen dat dit voorbeeld, samen met de andere bronnen die op internet beschikbaar zijn, enige opwinding oplevert en u aan het denken zet over hoe u generatoren in uw eigen code kunt gebruiken. Versies van Firefox beginnend met 31 en Chrome beginnend met 39 ondersteunen native generators. Het Regenerator-project biedt generatorondersteuning voor andere browsers, en het gebruik van Traceur is ook een optie.

Met dank aan Erik Arvidsson voor zijn hulp bij het beoordelen van dit artikel.