Signatur
Beschreibung
GeneratorFunction ist kein globales Objekt. Du erreichst den Konstruktor über den Prototyp einer beliebigen Generatorfunktion: const GeneratorFunction = function* () {}.constructor;. Er funktioniert wie Function(), erzeugt aber eine Generatorfunktion, also eine Funktion, die mit function* deklariert worden sein könnte und beim Aufruf ein Generator-Objekt zurückgibt.
Die letzten Argumente sind Strings: Alle bis auf das letzte werden als Parameternamen interpretiert, das letzte als Funktionsrumpf. Im Rumpf darfst du yield und yield* verwenden. Der Aufruf mit oder ohne new hat dieselbe Wirkung.
Solche Funktionen werden immer im globalen Gültigkeitsbereich erzeugt. Sie bilden also keine Closure über den umgebenden Kontext und sehen nur ihre eigenen lokalen und globalen Variablen. Das ist ein wichtiger Unterschied zu eval() mit einem function*-Ausdruck.
Brauchen wirst du den Konstruktor selten. Sinnvoll ist er etwa bei Code-Generatoren, Lern-Tools oder Sandboxes, in denen Generatorlogik erst zur Laufzeit als Text vorliegt. In normalem Anwendungscode solltest du immer die Syntax function* verwenden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $arg1, …, argN | string | Optionale Namen der formalen Parameter als Strings. Mehrere Namen dürfen auch kommagetrennt in einem String stehen, z. B. "a, b". Standardwerte und Rest-Parameter wie "x = 1" oder "...rest" sind erlaubt. |
|
| $functionBody | string | "" | String mit den JavaScript-Anweisungen des Funktionsrumpfs, darunter yield-Ausdrücke. Fehlt er, entsteht eine leere Generatorfunktion. |
Rückgabewert
Generator-Objekt, das sowohl iterierbar als auch ein Iterator ist.Beispiele
Konstruktor beschaffen und Generator erzeugen
// GeneratorFunction ist nicht global – über den Prototyp holen
const GeneratorFunction = function* () {}.constructor;
const zaehler = new GeneratorFunction('start', 'ende', `
for (let i = start; i <= ende; i++) {
yield i;
}
`);
const gen = zaehler(1, 3);
console.log(gen.next());
console.log([...zaehler(5, 7)]);
Typprüfung: Ist eine Funktion ein Generator?
const GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor;
const istGeneratorFunktion = (fn) => fn instanceof GeneratorFunction;
function* ids() { yield 1; }
const normal = () => 1;
console.log(istGeneratorFunktion(ids));
console.log(istGeneratorFunktion(normal));
console.log(Object.prototype.toString.call(ids));
Kein Zugriff auf lokale Variablen (globaler Scope)
const GeneratorFunction = function* () {}.constructor;
const erzeuge = () => {
const faktor = 10; // lokal – für den erzeugten Generator unsichtbar
return new GeneratorFunction('werte', `
for (const w of werte) yield w * (typeof faktor === 'undefined' ? 1 : faktor);
`);
};
console.log([...erzeuge()([1, 2, 3])]);
Generator aus Konfigurationstext bauen
const GeneratorFunction = function* () {}.constructor;
// z. B. aus einer vertrauenswürdigen, internen Vorlage
const vorlage = { params: ['n'], body: 'let [a, b] = [0, 1]; while (n-- > 0) { yield a; [a, b] = [b, a + b]; }' };
const fibonacci = new GeneratorFunction(...vorlage.params, vorlage.body);
console.log(Array.from(fibonacci(8)));
// Wichtig · Fallstricke
- Sicherheit: Der Konstruktor wertet Strings als Code aus, genau wie
eval()undFunction(). Übergib niemals ungeprüfte Benutzereingaben, sonst öffnest du Code-Injection- bzw. XSS-Lücken. - CSP: Bei einer Content Security Policy ohne
'unsafe-eval'wirft der Aufruf einenEvalError. Das gilt auch in vielen Browser-Erweiterungen. - Kein globaler Name:
new GeneratorFunction()direkt aufzurufen, wirft einenReferenceError. Hol dir den Konstruktor zuerst überfunction* () {}.constructor. - Kein Closure: Die erzeugte Funktion läuft im globalen Scope und sieht keine lokalen Variablen der Aufrufstelle.
- Performance: Der Code wird bei jedem Aufruf neu geparst und ist schwerer zu optimieren. Die Syntax
function*ist fast immer die bessere Wahl. - Für asynchrone Generatoren gibt es analog
AsyncGeneratorFunction(überasync function* () {}.constructor). - Kompatibilität: in allen modernen Browsern und in Node.js ab Version 4 verfügbar (Baseline).