Iterator()-Konstruktor
Baseline 2025>
Neu verfügbar
Seit März 2025 funktioniert diese Funktion auf aktuellen Geräten und in aktuellen Browserversionen. Auf älteren Geräten oder in älteren Browsern funktioniert sie möglicherweise nicht.
Der Iterator()-Konstruktor ist als Oberklasse für andere Klassen gedacht, die Iteratoren erzeugen. Wird er selbst direkt instanziiert, löst er einen Fehler aus.
Syntax
new Iterator()
Parameter
Keine.
Rückgabewert
Ein neues Iterator-Objekt.
Ausnahmen
TypeError-
Wenn
new.targetdieIterator-Funktion selbst ist, derIterator-Konstruktor also direkt instanziiert wird.
Beschreibung
Iterator ist eine abstrakte Klasse: Sie stellt ihren Unterklassen gemeinsame Funktionen bereit, ist aber nicht dafür vorgesehen, selbst instanziiert zu werden. Sie ist die Oberklasse aller anderen Iterator-Klassen und dient als Grundlage für Unterklassen, die bestimmte Iterationsalgorithmen implementieren. Dazu muss jede Unterklasse von Iterator eine next()-Methode implementieren, wie es das Iterator-Protokoll verlangt. Da Iterator selbst keine next()-Methode bereitstellt, ist es nicht sinnvoll, Iterator direkt zu instanziieren.
Sie können auch Iterator.from() verwenden, um aus einem vorhandenen iterierbaren Objekt oder Iterator-Objekt eine Iterator-Instanz zu erstellen.
Beispiele
>Eine Unterklasse von Iterator erstellen
Das folgende Beispiel definiert eine benutzerdefinierte Datenstruktur namens Range, über die iteriert werden kann. Um ein Objekt iterierbar zu machen, können wir eine [Symbol.iterator]()-Methode in Form einer Generatorfunktion bereitstellen:
class Range {
#start;
#end;
#step;
constructor(start, end, step = 1) {
this.#start = start;
this.#end = end;
this.#step = step;
}
*[Symbol.iterator]() {
for (let value = this.#start; value <= this.#end; value += this.#step) {
yield value;
}
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num);
}
Das funktioniert, ist aber nicht so elegant wie die Funktionsweise integrierter Iteratoren. Es gibt zwei Probleme:
- Der zurückgegebene Iterator erbt von
Generator. Dadurch wirken sich Änderungen anGenerator.prototypeauf ihn aus, was die Abstraktion durchbricht. - Der zurückgegebene Iterator erbt nicht von einem benutzerdefinierten Prototyp. Das erschwert es, dem Iterator zusätzliche Methoden hinzuzufügen.
Wir können die Implementierung integrierter Iteratoren, etwa der Map-Iteratoren, nachbilden, indem wir eine Unterklasse von Iterator erstellen. So können wir zusätzliche Eigenschaften wie [Symbol.toStringTag] definieren, während die Iterator-Hilfsmethoden für den zurückgegebenen Iterator verfügbar sind.
class Range {
#start;
#end;
#step;
constructor(start, end, step = 1) {
this.#start = start;
this.#end = end;
this.#step = step;
}
static #RangeIterator = class extends Iterator {
#cur;
#s;
#e;
constructor(range) {
super();
this.#cur = range.#start;
this.#s = range.#step;
this.#e = range.#end;
}
static {
Object.defineProperty(this.prototype, Symbol.toStringTag, {
value: "Range Iterator",
configurable: true,
enumerable: false,
writable: false,
});
// Avoid #RangeIterator from being accessible outside
delete this.prototype.constructor;
}
next() {
if (this.#cur > this.#e) {
return { value: undefined, done: true };
}
const res = { value: this.#cur, done: false };
this.#cur += this.#s;
return res;
}
};
[Symbol.iterator]() {
return new Range.#RangeIterator(this);
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num);
}
Dieses Muster eignet sich, wenn Sie viele benutzerdefinierte Iteratoren erstellen möchten. Wenn Sie bereits ein iterierbares Objekt oder Iterator-Objekt haben, das nicht von Iterator erbt, und lediglich Iterator-Hilfsmethoden darauf aufrufen möchten, können Sie mit Iterator.from() eine einmalige Iterator-Instanz erstellen.
Spezifikationen
| Spezifikation |
|---|
| ECMAScript® 2027 Language Specification> # sec-iterator-constructor> |