Generatoren – die gnadenhaften Bits

Die ECMAScript 6-Entwurfsspezifikation hat modernen JavaScript-Entwicklern bereits viele neue Möglichkeiten eröffnet. In einem vorherigen Beitrag haben wir einige neue Sammlungsklassen und for..of-Iterationsschleifen behandelt. In diesem Beitrag geht es um etwas, das eng mit for..of-Schleifen zusammenhängt: Generatorfunktionen.

Es gibt bereits eine Vielzahl von tollen Materialien, die das Warum und Wie der Verwendung von Generatoren behandeln. Kurz gesagt: Generatoren sind spezielle Funktionen, die Iteratoren erstellen. Iteratoren sind Objekte mit einer next()-Methode, die aufgerufen werden kann, um einen Wert abzurufen. Innerhalb einer Generatorfunktion liefert das Keyword yield den Wert für next(). Durch die Verwendung von yield wird die Ausführung der Generatorfunktion angehalten und der Status bleibt erhalten, bis next() wieder aufgerufen wird. Der Code wird dann fortgesetzt, bis ein anderer Wert yield wird (oder die Generatorfunktion beendet wird). Es gibt mehrere kanonische Anwendungsfälle für Generatorfunktionen, z. B. die Iteration über die Zahlen in der Fibonacci-Folge.

Nachdem wir die Grundlagen geklärt haben, sehen wir uns ein JavaScript-Beispiel an, das einige der Fallstricke bei der Arbeit mit Generatoren behandelt. Der Code ist ausführlich kommentiert und Sie können sich mit der Liveversion des Codes vertraut machen, bevor Sie ihn durchgehen:

Was sind also die wichtigsten Erkenntnisse aus dem Code?

Erstens: Das Erstellen eines Generators führt zu einem eindeutigen Iterator mit einem eigenen Zustand. Sie können dem Generatorkonstruktor Parameter übergeben, mit denen sich das Verhalten steuern lässt.

Zweitens können Sie beim Aufrufen der next()-Methode eines Iterators einen Parameter übergeben. Dieser Wert wird dem Wert zugewiesen, der sich links in der yield-Anweisung aus dem vorherigen Aufruf des Iterators befindet. So lässt sich die Ausgabe des Iterationsobjekts variieren. Hier wird damit gesteuert, ob das Wort in Großbuchstaben oder Kleinbuchstaben ausgegeben wird. Wenn Sie den allerersten Wert beeinflussen möchten, tun Sie dies über einen Parameter für den Konstruktor des Generators.

Außerdem können Generatoren entweder endliche oder unendliche Iteratoren erzeugen. Wenn Sie mit einem unendlichen Iterator arbeiten, müssen Sie eine Art Endbedingung basierend auf dem Wert yielded haben. Es ist sehr einfach, versehentlich endlose Schleifen zu schreiben, insbesondere wenn Sie for..of für die Iteration verwenden. Wenn Sie über next() mit einem endlichen Iterator arbeiten, gibt das Attribut .done des zurückgegebenen Objekts an, ob die Iteration abgeschlossen ist.

Wir hoffen, dass dieses Beispiel und die anderen im Web verfügbaren Ressourcen Sie inspirieren und dazu anregen, darüber nachzudenken, wie Sie Generatoren in Ihrem eigenen Code verwenden können. Versionen von Firefox ab 31 und Chrome ab 39 unterstützen Generatoren nativ. Das Regenerator-Projekt bietet Generatorunterstützung für andere Browser. Auch die Verwendung von Traceur ist eine Option.

Vielen Dank an Erik Arvidsson für die Hilfe bei der Überprüfung dieses Artikels.