Start · Sprachen · JavaScript · Referenz · Symbol.matchAll

Symbol.matchAll

Eigenschaft

Das bekannte Symbol <code>Symbol.matchAll</code> legt die Methode fest, die <code>String.prototype.matchAll()</code> aufruft, um alle Treffer als Iterator zu liefern.

seit JavaScript ES2020 (Baseline: alle modernen Browser, Node.js 1 Kategorie: method-property

Signatur

Symbol.matchAll

Beschreibung

Symbol.matchAll ist ein sogenanntes well-known Symbol, also ein fest eingebautes Symbol. Wenn du str.matchAll(muster) aufrufst, prüft die Engine, ob muster eine Methode unter dem Schlüssel muster[Symbol.matchAll] hat. Falls ja, wird sie mit dem String als Argument aufgerufen, und ihr Rückgabewert (ein Iterator) wird direkt weitergegeben.

Standardmäßig ist diese Methode nur auf RegExp.prototype definiert. RegExp.prototype[Symbol.matchAll](str) kopiert den regulären Ausdruck (über Symbol.species) und liefert einen RegExpStringIterator, der nacheinander alle Treffer mit Gruppen und Index ausgibt.

Das Symbol ist vor allem dann nützlich, wenn du:

  • eigene Suchobjekte baust, die sich wie ein regulärer Ausdruck mit matchAll() verwenden lassen (z. B. Parser, Tokenizer),
  • in einer Unterklasse von RegExp das Trefferformat anpassen willst,
  • die Iteratorlogik von RegExp direkt aufrufen willst, ohne den Umweg über den String.

Die Eigenschaft selbst ist nicht beschreibbar, nicht aufzählbar und nicht konfigurierbar. Symbol.matchAll liefert also immer dasselbe Symbol, auch über verschiedene Realms (iframes) hinweg.

Parameter

Name Typ Default Beschreibung
$string Pflicht string Parameter der Protokoll-Methode obj[Symbol.matchAll](string): der String, der durchsucht werden soll. String.prototype.matchAll() übergibt hier den String, auf dem sie aufgerufen wurde. Symbol.matchAll selbst ist eine Eigenschaft und nimmt keine Parameter.

Rückgabewert

Typ
symbol
Beschreibung
Das bekannte Symbol Symbol.matchAll. Eine Methode, die unter diesem Schlüssel hinterlegt ist, sollte einen Iterator zurückgeben (z. B. über eine Generator-Funktion).

Beispiele

Das Symbol und die eingebaute RegExp-Implementierung

console.log(typeof Symbol.matchAll);
console.log(Symbol.matchAll.toString());
console.log(typeof RegExp.prototype[Symbol.matchAll]);

// Direkter Aufruf, ohne String.prototype.matchAll()
const zahlen = /\d+/g;
const treffer = [...zahlen[Symbol.matchAll]('a1b22c333')].map((m) => m[0]);
console.log(treffer);
symbol Symbol(Symbol.matchAll) function [ '1', '22', '333' ]

Eigenes Suchobjekt für String.prototype.matchAll()

// Ein Objekt ohne RegExp, das lange Wörter findet
const langeWoerter = {
  *[Symbol.matchAll](str) {
    for (const wort of str.split(/\s+/)) {
      if (wort.length > 4) yield wort;
    }
  }
};

const satz = 'Das ist ein langes Beispiel';
console.log([...satz.matchAll(langeWoerter)]);
[ 'langes', 'Beispiel' ]

RegExp-Unterklasse liefert nur benannte Gruppen

class GruppenRegExp extends RegExp {
  *[Symbol.matchAll](str) {
    // Standardlogik weiterverwenden, Ergebnis umformen
    for (const m of super[Symbol.matchAll](str)) {
      yield { ...m.groups };
    }
  }
}

const query = new GruppenRegExp('(?<key>\\w+)=(?<val>\\w+)', 'g');
const paare = [...'a=1&b=2&c=3'.matchAll(query)];
console.log(JSON.stringify(paare));
[{"key":"a","val":"1"},{"key":"b","val":"2"},{"key":"c","val":"3"}]

// Wichtig · Fallstricke

  • g-Flag ist Pflicht: Erkennt matchAll() das Argument als RegExp (über Symbol.match), wirft es einen TypeError, wenn das Flag g fehlt, und zwar bevor [Symbol.matchAll] aufgerufen wird. Das gilt auch für Unterklassen.
  • Kein RegExp und keine eigene Methode: Hat das Argument keine Methode [Symbol.matchAll], wird es per new RegExp(arg, 'g') umgewandelt. Strings mit Sonderzeichen wie . oder * werden dann als Muster interpretiert.
  • Rückgabe muss iterierbar sein: matchAll() prüft den Rückgabewert nicht. Liefert deine Methode keinen Iterator, schlagen erst Spread oder for...of fehl. Am einfachsten ist eine Generator-Methode (*[Symbol.matchAll]).
  • Kein Zustand am Original: Die eingebaute Implementierung kopiert den RegExp, deshalb bleibt lastIndex am Original unverändert. Eigene Implementierungen sollten das auch so halten.
  • Kompatibilität: Unterstützt ab Chrome 73, Firefox 67, Safari 13 und Node.js 12. Ältere Umgebungen brauchen ein Polyfill (z. B. core-js).