Wersja robocza specyfikacji ECMAScript 6 już wcześniej sprawiała wiele radości współczesnym programistom JavaScriptu. W poprzednim poście omówiliśmy kilka nowych klas kolekcji i pętli iteracji for..of
. Z tego posta dowiesz się, co idzie w parze z pętlami for..of
, czyli funkcjami generatorów.
Istnieje już host doskonałych materiałów, które wyjaśniają, dlaczego i jak korzystać z generatorów. W skrócie, generatory to specjalne funkcje, które tworzą iteratory, a itetory to obiekty z metodą next()
, którą można wywołać w celu uzyskania wartości. W funkcji generatora słowo kluczowe yield
zawiera wartość next()
. Zastosowanie funkcji yield
zawiesza wykonanie funkcji generatora, zachowując stan do czasu ponownego wywołania funkcji next()
. Wtedy kod uruchamia się z powrotem i działa tak dalej, aż yield
zmieni wartość (lub do chwili zakończenia działania funkcji generatora). Istnieje kilka kanonicznych przypadków użycia funkcji generatorów, np. używanie ich do powtarzania liczb z ciągu Fibonacciego.
Skoro już omówiliśmy podstawy, przejdźmy do szczegółów dzięki przykładowi JavaScriptu, w którym omówiono niektóre z ciekawych aspektów pracy z generatorami. W całym tekście pojawia się wiele komentarzy, a przed przeczytaniem można wypróbować wersję online kodu:
Jakie są więc istotne wnioski z kodu?
Po pierwsze, skonstruowanie generatora powoduje utworzenie unikalnego iteratora o odrębnym stanie. Następnie można przekazać do konstruktora generatora parametry, które mogą kontrolować jego działanie.
Po drugie, możesz przekazać parametr podczas wywoływania metody next()
iteratora. Wartość ta zostanie przypisana do elementu znajdującego się po lewej stronie instrukcji yield
z poprzedniego wywołania iteratora. To świetny sposób na zróżnicowanie danych wyjściowych iteratora. Użyjemy go do określenia, czy zostanie wygenerowane słowo pisane wielkimi literami. Jeśli chcesz wpłynąć na pierwszą otrzymaną wartość, zrób to za pomocą parametru w konstruktorze generatora.
Generatory mogą także tworzyć iteratory o skończonym lub nieograniczonym zakresie. Jeśli korzystasz z iteratora nieskończonego, upewnij się, że został określony warunek końcowy oparty na wartości yield
ed. Bardzo łatwo jest przypadkowo utworzyć pętlę nieskończoną, zwłaszcza gdy używasz funkcji for..of
do iteracji. Jeśli pracujesz z iteratorem skończonym za pomocą wywołań funkcji next()
, zwracana właściwość .done
obiektu sygnalizuje, czy iteracja została zakończona.
Mamy nadzieję, że ten przykład wraz z innymi zasobami dostępnymi w internecie wzbudzi zainteresowanie i zachęci do zastanowienia się nad wykorzystaniem generatorów we własnym kodzie. Wersje przeglądarki Firefox zaczynające się od wersji 31 oraz Chrome i 39 natywnie obsługują generatory. Projekt Regenerator oferuje obsługę generatorów w innych przeglądarkach. Użycie systemu Traceur jest też możliwe.
Dziękuję Erikowi Arvidssonowi za pomoc w przeczytaniu tego artykułu.