Signatur
Beschreibung
Die Methode [Symbol.matchAll]() ist der interne Mechanismus hinter String.prototype.matchAll(). Bei einem Aufruf wie str.matchAll(regexp) sucht die Engine auf dem Argument nach einer Methode unter dem Schlüssel Symbol.matchAll und ruft diese mit dem String auf. Bei RegExp-Objekten ist das genau diese Methode.
Intern passiert Folgendes: Aus dem regulären Ausdruck wird über den Species-Konstruktor (RegExp[Symbol.species]) eine Kopie mit denselben Flags erzeugt. Ihr lastIndex wird auf den aktuellen lastIndex des Originals gesetzt. Zurück kommt ein RegExp String Iterator, der die Treffer erst beim Weiterschalten (also „lazy“) nacheinander liefert. Jeder Treffer ist ein Array wie bei RegExp.prototype.exec(), also mit den Eigenschaften index, input, groups und, falls das Flag d gesetzt ist, auch indices. Weil nur die Kopie verändert wird, bleibt der lastIndex des ursprünglichen Ausdrucks unverändert.
Direkt aufrufen muss man die Methode selten. Wichtig ist sie vor allem, wenn man RegExp ableitet und das Verhalten von matchAll() anpassen will, zum Beispiel um ein Array statt eines Iterators zurückzugeben oder Treffer zu filtern. Auch eigene Objekte, die keine regulären Ausdrücke sind, können Symbol.matchAll umsetzen und damit an String.prototype.matchAll() übergeben werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $str Pflicht | string | Der String, in dem gesucht wird. Werte, die kein String sind, werden mit String() umgewandelt. |
Rückgabewert
exec(). Gibt es keine Treffer, ist der Iterator sofort erschöpft. Ohne Flag g liefert er höchstens einen Treffer.Beispiele
Direkter Aufruf: alle Zahlen aus einem Datum holen
const re = /[0-9]+/g;
const str = '2016-01-02';
const iterator = re[Symbol.matchAll](str);
console.log(Array.from(iterator, (m) => m[0]));
Unterklasse: matchAll() gibt ein Array statt eines Iterators zurück
class ArrayMatchRegExp extends RegExp {
[Symbol.matchAll](str) {
const iterator = RegExp.prototype[Symbol.matchAll].call(this, str);
return Array.from(iterator);
}
}
const re = new ArrayMatchRegExp('(?<jahr>\\d{4})-(?<monat>\\d{2})', 'g');
const text = 'Release 2023-05, Update 2024-11';
const treffer = text.matchAll(re); // ruft re[Symbol.matchAll] auf
console.log(Array.isArray(treffer));
console.log(treffer.map((m) => `${m.groups.monat}/${m.groups.jahr}`));
lastIndex wird übernommen, das Original bleibt unverändert
const re = /a/g;
re.lastIndex = 2;
const positionen = [...re[Symbol.matchAll]('aaaa')].map((m) => m.index);
console.log(positionen); // Suche beginnt bei Index 2
console.log(re.lastIndex); // Original unverändert
Ohne g-Flag: direkter Aufruf liefert nur einen Treffer
const re = /\d+/; // kein g-Flag
console.log([...re[Symbol.matchAll]('1 2 3')].map((m) => m[0]));
try {
'1 2 3'.matchAll(re);
} catch (err) {
console.log(err.constructor.name);
}
// Wichtig · Fallstricke
- g-Flag:
String.prototype.matchAll()wirft einenTypeError, wenn einRegExpohne Flaggübergeben wird. Das passiert, bevor[Symbol.matchAll]aufgerufen wird. Ruft man die Methode direkt auf, gibt es keinen Fehler, aber der Iterator liefert nur den ersten Treffer. - Lazy und nur einmal nutzbar: Der Iterator sucht erst beim Weiterschalten und ist danach erschöpft. Wer die Treffer mehrfach braucht, wandelt sie mit
Array.from()oder dem Spread-Operator um. - Leere Treffer: Bei Mustern, die leere Treffer finden können (z. B.
/x*/g), wirdlastIndexautomatisch weitergeschoben, damit keine Endlosschleife entsteht. Mit Flaguodervgeschieht das nach Unicode-Codepoints. - Species: Die interne Kopie wird über
this.constructor[Symbol.species]erzeugt. Überschreibt eine UnterklasseSymbol.species, beeinflusst das den verwendeten Matcher. - Kompatibilität: Ab ES2020, in allen modernen Browsern und ab Node.js 12 verfügbar. Nicht im Internet Explorer.