Start · Sprachen · JavaScript · Referenz · new GeneratorFunction()

new GeneratorFunction()

Methode

Der Konstruktor <code>GeneratorFunction()</code> erzeugt zur Laufzeit eine neue Generatorfunktion aus Strings für Parameter und Funktionsrumpf.

seit JavaScript ES2015 Kategorie: method-property

Signatur

new GeneratorFunction(arg1, arg2, /* …, */ argN, functionBody)

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

Typ
GeneratorFunction
Beschreibung
Eine neue Generatorfunktion. Ihr Aufruf liefert ein 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)]);
{ value: 1, done: false } [ 5, 6, 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));
true false [object GeneratorFunction]

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])]);
[ 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)));
[ 0, 1, 1, 2, 3, 5, 8, 13 ]

// Wichtig · Fallstricke

  • Sicherheit: Der Konstruktor wertet Strings als Code aus, genau wie eval() und Function(). Ü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 einen EvalError. Das gilt auch in vielen Browser-Erweiterungen.
  • Kein globaler Name: new GeneratorFunction() direkt aufzurufen, wirft einen ReferenceError. Hol dir den Konstruktor zuerst über function* () {}.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 (über async function* () {}.constructor).
  • Kompatibilität: in allen modernen Browsern und in Node.js ab Version 4 verfügbar (Baseline).