Leser wie Sie helfen, MUO zu unterstützen. Wenn Sie über Links auf unserer Website einen Kauf tätigen, erhalten wir möglicherweise eine Affiliate-Provision. Weiterlesen.

Das Iterieren über Datensammlungen mit herkömmlichen Schleifen kann schnell umständlich und langsam werden, insbesondere wenn es um große Datenmengen geht.

JavaScript-Generatoren und -Iteratoren bieten eine Lösung zum effizienten Iterieren großer Datensammlungen. Mit ihnen können Sie den Iterationsfluss steuern, Werte einzeln ausgeben und den Iterationsprozess anhalten und fortsetzen.

Hier behandeln Sie die Grundlagen und Interna eines JavaScript-Iterators und wie Sie einen Iterator manuell und mit einem Generator generieren können.

JavaScript-Iteratoren

Ein Iterator ist ein JavaScript-Objekt, das das Iterator-Protokoll implementiert. Diese Objekte tun dies, indem sie a nächste Methode. Diese Methode gibt ein Objekt zurück, das die implementiert IteratorErgebnis Schnittstelle.

Der IteratorErgebnis Schnittstelle besteht aus zwei Eigenschaften:

instagram viewer
Erledigt Und Wert. Der Erledigt Eigenschaft ist ein boolescher Wert, der zurückgegeben wird FALSCH ob der Iterator den nächsten Wert in seiner Sequenz erzeugen kann oder WAHR wenn der Iterator seine Sequenz abgeschlossen hat.

Der Wert Die Eigenschaft ist ein JavaScript-Wert, der vom Iterator während seiner Sequenz zurückgegeben wird. Wenn ein Iterator seine Sequenz abschließt (when ErledigtWAHR), gibt diese Eigenschaft zurück nicht definiert.

Wie der Name schon sagt, ermöglichen Iteratoren das „Iterieren“ über JavaScript-Objekte wie Arrays oder Maps. Dieses Verhalten ist aufgrund des iterierbaren Protokolls möglich.

In JavaScript ist das iterierbare Protokoll eine Standardmethode zum Definieren von Objekten, über die Sie iterieren können, z. B. in a für... von Schleife.

Zum Beispiel:

konst Früchte = ["Banane", "Mango", "Apfel", "Trauben"];

für (konst Iterator von Früchte) {
Konsole.log (Iterator);
}

/*
Banane
Mango
Apfel
Trauben
*/

Dieses Beispiel iteriert über die Früchte Array mit a für... von Schleife. Bei jeder Iteration protokolliert es den aktuellen Wert in der Konsole. Dies ist möglich, weil Arrays iterierbar sind.

Einige JavaScript-Typen wie Arrays, Strings, Sätze und Karten, sind integrierte Iterables, weil sie (oder eines der Objekte in ihrer Prototypenkette) eine implementieren @@Iterator Methode.

Andere Typen wie Objects sind standardmäßig nicht iterierbar.

Zum Beispiel:

konst iterObject = {
Autos: ["Tesla", "BMW", "Toyota"],
Tiere: ["Katze", "Hund", "Hamster"],
Essen: ["Burger", "Pizza", "Pasta"],
};

für (konst Iterator von iterObject) {
Konsole.log (Iterator);
}

// TypeError: iterObject ist nicht iterierbar

Dieses Beispiel zeigt, was passiert, wenn Sie versuchen, ein Objekt zu durchlaufen, das nicht iterierbar ist.

Ein Objekt iterierbar machen

Um ein Objekt iterierbar zu machen, müssen Sie a implementieren Symbol.iterator Methode auf dem Objekt. Um iterierbar zu werden, muss diese Methode ein Objekt zurückgeben, das die implementiert IteratorErgebnis Schnittstelle.

Der Symbol.iterator Symbol erfüllt den gleichen Zweck wie @@Iterator und kann austauschbar in „Spezifikation“ verwendet werden, aber nicht in Code als @@Iterator ist keine gültige JavaScript-Syntax.

Die folgenden Codeblöcke bieten ein Beispiel dafür, wie Sie ein Objekt mithilfe von iterierbar machen iterObject.

Fügen Sie zuerst die hinzu Symbol.iterator Methode zu iterObject verwenden eine Funktion Erklärung.

So:

iterObject[Symbol.Iterator] = Funktion () {
// Nachfolgende Codeblöcke kommen hierher...
}

Als Nächstes müssen Sie auf alle Schlüssel in dem Objekt zugreifen, das Sie iterierbar machen möchten. Sie können auf die Schlüssel zugreifen, indem Sie die Objekt.Schlüssel -Methode, die ein Array der aufzählbaren Eigenschaften eines Objekts zurückgibt. Um ein Array von zurückzugeben iterObject's Schlüssel, übergeben Sie die Das Schlüsselwort als Argument für Objekt.Schlüssel.

Zum Beispiel:

lassen objProperties = Objekt.Schlüssel(Das)

Durch den Zugriff auf dieses Array können Sie das Iterationsverhalten des Objekts definieren.

Als Nächstes müssen Sie die Iterationen des Objekts verfolgen. Dies können Sie mit Zählervariablen erreichen.

Zum Beispiel:

lassen PropertyIndex = 0;
lassen KindIndex = 0;

Sie verwenden die erste Zählervariable, um die Objekteigenschaften zu verfolgen, und die zweite, um die untergeordneten Elemente der Eigenschaft zu verfolgen.

Als Nächstes müssen Sie die implementieren und zurückgeben nächste Methode.

So:

zurückkehren {
nächste() {
// Nachfolgende Codeblöcke kommen hierher...
}
}

Im Inneren des nächste -Methode müssen Sie einen Grenzfall behandeln, der auftritt, wenn über das gesamte Objekt iteriert wurde. Um den Grenzfall zu behandeln, müssen Sie ein Objekt mit zurückgeben Wert einstellen nicht definiert Und Erledigt einstellen WAHR.

Wenn dieser Fall nicht behandelt wird, führt der Versuch, über das Objekt zu iterieren, zu einer Endlosschleife.

So gehen Sie mit dem Grenzfall um:

Wenn (PropertyIndex > objProperties.Länge- 1) {
zurückkehren {
Wert: nicht definiert,
Erledigt: WAHR,
};
}

Als Nächstes müssen Sie mithilfe der zuvor deklarierten Zählervariablen auf die Objekteigenschaften und ihre untergeordneten Elemente zugreifen.

So:

// Zugriff auf übergeordnete und untergeordnete Eigenschaften
konst Eigenschaften = Das[objProperties[propertyIndex]];

konst Eigenschaft = Eigenschaften [KindIndex];

Als nächstes müssen Sie eine Logik zum Inkrementieren der Zählervariablen implementieren. Die Logik sollte das zurücksetzen KindIndex wenn keine Elemente mehr im Array einer Eigenschaft vorhanden sind, und zur nächsten Eigenschaft im Objekt wechseln. Außerdem sollte es inkrementieren KindIndex, wenn es noch Elemente im Array der aktuellen Eigenschaft gibt.

Zum Beispiel:

// Indexerhöhungslogik
if (childIndex >= properties.length - 1) {
// wenn es keine weiteren Elemente im untergeordneten Array gibt
// zurücksetzenKindIndex
KindIndex = 0;

// Zur nächsten Eigenschaft wechseln
PropertyIndex++;
} anders {
// Gehe zum nächsten Element im untergeordneten Array
childIndex++
}

Geben Sie schließlich ein Objekt mit dem zurück Erledigt Eigenschaft gesetzt auf FALSCH und das Wert -Eigenschaft auf das aktuelle untergeordnete Element in der Iteration festgelegt.

Zum Beispiel:

zurückkehren {
Erledigt: FALSCH,
Wert: Eigentum,
};

Ihr abgeschlossen Symbol.iterator Die Funktion sollte dem folgenden Codeblock ähneln:

iterObject[Symbol.Iterator] = Funktion () {
konst objProperties = Objekt.Schlüssel(Das);
lassen PropertyIndex = 0;
lassen KindIndex = 0;

zurückkehren {
nächste: () => {
// Randfall behandeln
Wenn (PropertyIndex > objProperties.Länge- 1) {
zurückkehren {
Wert: nicht definiert,
Erledigt: WAHR,
};
}

// Zugriff auf übergeordnete und untergeordnete Eigenschaften
konst Eigenschaften = Das[objProperties[propertyIndex]];

konst Eigenschaft = Eigenschaften [KindIndex];

// Indexerhöhungslogik
if (childIndex >= properties.length - 1) {
// wenn es keine weiteren Elemente im untergeordneten Array gibt
// zurücksetzenKindIndex
KindIndex = 0;

// Zur nächsten Eigenschaft wechseln
PropertyIndex++;
} anders {
// Gehe zum nächsten Element im untergeordneten Array
childIndex++
}

zurückkehren {
Erledigt: FALSCH,
Wert: Eigentum,
};
},
};
};

Laufen a für... von Schleife an iterObject Nach dieser Implementierung wird kein Fehler ausgegeben, da a implementiert wird Symbol.iterator Methode.

Das manuelle Implementieren von Iteratoren, wie wir es oben getan haben, wird nicht empfohlen, da es sehr fehleranfällig ist und die Logik schwer zu verwalten sein kann.

JavaScript-Generatoren

Ein JavaScript-Generator ist eine Funktion, deren Ausführung Sie jederzeit anhalten und fortsetzen können. Dieses Verhalten ermöglicht es, im Laufe der Zeit eine Folge von Werten zu erzeugen.

Eine Generatorfunktion, bei der es sich um eine Funktion handelt, die einen Generator zurückgibt, bietet eine Alternative zum Erstellen von Iteratoren.

Sie können eine Generatorfunktion genauso erstellen wie eine Funktionsdeklaration in JavaScript. Der einzige Unterschied besteht darin, dass Sie ein Sternchen anhängen müssen (*) zum Funktionsschlüsselwort.

Zum Beispiel:

Funktion* Beispiel () {
zurückkehren"Generator"
}

Wenn Sie eine normale Funktion in JavaScript aufrufen, gibt sie den von ihr angegebenen Wert zurück zurückkehren Stichwort bzw nicht definiert ansonsten. Aber eine Generatorfunktion gibt nicht sofort einen Wert zurück. Es gibt ein Generator-Objekt zurück, das Sie einer Variablen zuweisen können.

Um auf den aktuellen Wert des Iterators zuzugreifen, rufen Sie die auf nächste -Methode für das Generator-Objekt.

Zum Beispiel:

konst gen = beispiel();

console.log (gen.next()); // { Wert: 'Generator', Erledigt: WAHR }

Im obigen Beispiel ist die Wert Eigentum kam von a zurückkehren Schlüsselwort, wodurch der Generator effektiv beendet wird. Dieses Verhalten ist bei Generatorfunktionen im Allgemeinen unerwünscht, da sie sich von normalen Funktionen durch die Möglichkeit unterscheiden, die Ausführung anzuhalten und neu zu starten.

Das yield-Schlüsselwort

Der Ertrag Das Schlüsselwort bietet eine Möglichkeit, Werte in Generatoren zu durchlaufen, indem die Ausführung einer Generatorfunktion angehalten und der darauf folgende Wert zurückgegeben wird.

Zum Beispiel:

Funktion* Beispiel() {
Ertrag"Modell S"
Ertrag"Modell X"
Ertrag"Cyber-Truck"

zurückkehren"Tesla"
}

konst gen = beispiel();

console.log (gen.next()); // { Wert: 'Modell S', Erledigt: FALSCH }

Im obigen Beispiel, wenn die nächste Methode wird auf der aufgerufen Beispiel Generator, wird er jedes Mal pausieren, wenn er auf den trifft Ertrag Stichwort. Der Erledigt Eigenschaft wird auch auf gesetzt FALSCH bis es auf a trifft zurückkehren Stichwort.

Aufruf der nächste Methode mehrmals auf der Beispiel Generator, um dies zu demonstrieren, haben Sie Folgendes als Ausgabe.

console.log (gen.next()); // { Wert: 'Modell X', Erledigt: FALSCH }
console.log (gen.next()); // { Wert: "Cyber-Truck", Erledigt: FALSCH }
console.log (gen.next()); // { Wert: 'Tesla', Erledigt: WAHR }

Konsole.log (gen.next()); // { Wert: undefiniert, erledigt: wahr }

Sie können auch über ein Generator-Objekt iterieren, indem Sie verwenden für... von Schleife.

Zum Beispiel:

für (konst Iterator von gen) {
Konsole.log (Iterator);
}

/*
Modell S
Modell X
Cyber-Truck
*/

Verwendung von Iteratoren und Generatoren

Obwohl Iteratoren und Generatoren wie abstrakte Konzepte erscheinen mögen, sind sie es nicht. Sie können hilfreich sein, wenn Sie mit unendlichen Datenströmen und Datensammlungen arbeiten. Sie können sie auch verwenden, um eindeutige Kennungen zu erstellen. Auch Zustandsverwaltungsbibliotheken wie MobX-State-Tree (MST) verwenden sie unter der Haube.