Start · Sprachen · JavaScript · Referenz · RegExp.prototype[Symbol.replace]()

RegExp.prototype[Symbol.replace]()

Methode

Legt fest, wie <code>String.prototype.replace()</code> und <code>replaceAll()</code> ersetzen, wenn ein regulärer Ausdruck als Muster übergeben wird.

seit JavaScript ES2015 Kategorie: method-property

Signatur

RegExp.prototype[Symbol.replace](str, replacement)

Beschreibung

RegExp.prototype[Symbol.replace]() ist die interne Implementierung hinter str.replace(regex, ersatz) und str.replaceAll(regex, ersatz). Übergibt man ein Objekt mit einer [Symbol.replace]-Methode als Muster, ruft String.prototype.replace() diese Methode auf. Der Aufruf 'abc'.replace(/b/, 'x') ist also gleichbedeutend mit /b/[Symbol.replace]('abc', 'x').

Das Verhalten hängt vom g-Flag ab: Ohne g wird nur der erste Treffer ab lastIndex (bei y) bzw. ab Position 0 ersetzt. Mit g wird lastIndex auf 0 gesetzt und alle Treffer werden ersetzt. Intern wird dafür wiederholt this.exec() aufgerufen, weshalb Unterklassen das Verhalten durch Überschreiben von exec() oder direkt von [Symbol.replace] anpassen können.

Als Ersatz ist entweder ein String mit speziellen Mustern ($&, $1…$99, $<name>, $`, $', $$) oder eine Funktion erlaubt, die für jeden Treffer aufgerufen wird und den Ersatztext zurückgibt.

Direkt aufgerufen wird die Methode selten. Sinnvoll ist sie vor allem beim Ableiten eigener RegExp-Klassen oder beim Bau eigener Muster-Objekte, die mit replace() zusammenarbeiten sollen.

Parameter

Name Typ Default Beschreibung
$str Pflicht string Der String, in dem ersetzt werden soll. Andere Werte werden in einen String umgewandelt.
$replacement Pflicht string | Function Ersatztext mit optionalen $-Mustern oder eine Funktion (match, p1, …, offset, string, groups) => string, die pro Treffer aufgerufen wird. Ist es keine Funktion, wird der Wert in einen String umgewandelt.

Rückgabewert

Typ
string
Beschreibung
Ein neuer String, in dem ein Treffer (ohne g) oder alle Treffer (mit g) ersetzt wurden. Der Ausgangsstring bleibt unverändert.

Beispiele

Direkter Aufruf vs. String.prototype.replace()

const re = /-/g;
const datum = '2024-05-17';

console.log(re[Symbol.replace](datum, '.'));
console.log(datum.replace(re, '.'));
2024.05.17 2024.05.17

Benannte Gruppen und Ersatzfunktion

const re = /(?<jahr>\d{4})-(?<monat>\d{2})-(?<tag>\d{2})/g;
const text = 'Start: 2024-05-17, Ende: 2024-06-01';

// Ersatz über $<name>-Muster
console.log(re[Symbol.replace](text, '$<tag>.$<monat>.$<jahr>'));

// Ersatz über Funktion
const ergebnis = re[Symbol.replace](text, (...args) => {
  const { jahr, monat, tag } = args.at(-1);
  return `${Number(tag)}.${Number(monat)}.${jahr}`;
});
console.log(ergebnis);
Start: 17.05.2024, Ende: 01.06.2024 Start: 17.5.2024, Ende: 1.6.2024

Eigene RegExp-Unterklasse mit angepasstem Ersetzen

class ProtokollRegExp extends RegExp {
  [Symbol.replace](str, replacement) {
    let anzahl = 0;
    const ergebnis = super[Symbol.replace](str, (...args) => {
      anzahl++;
      return typeof replacement === 'function' ? replacement(...args) : replacement;
    });
    console.log(`${anzahl} Ersetzung(en)`);
    return ergebnis;
  }
}

const re = new ProtokollRegExp('passwort=\\S+', 'g');
const log = 'user=anna passwort=geheim; user=ben passwort=1234';
console.log(log.replace(re, 'passwort=***'));
2 Ersetzung(en) user=anna passwort=***; user=ben passwort=***

// Wichtig · Fallstricke

  • Nur ein Treffer ohne g: Ohne globales Flag wird nur der erste Treffer ersetzt. String.prototype.replaceAll() wirft bei einem RegExp ohne g einen TypeError, bevor [Symbol.replace] überhaupt aufgerufen wird.
  • lastIndex wird verändert: Bei g wird lastIndex zuerst auf 0 und am Ende wieder auf 0 gesetzt. Bei y ohne g beginnt die Suche an lastIndex, und der Wert wird danach aktualisiert. Das kann bei wiederverwendeten Regex-Objekten zu überraschenden Ergebnissen führen.
  • $ im Ersatzstring: Wenn der Ersatztext aus Benutzereingaben stammt, können $&, $1 usw. ungewollt ausgewertet werden. Maskiere $ als $$ oder nutze eine Ersatzfunktion, die den Text unverändert zurückgibt.
  • Leere Treffer: Muster wie /x*/g können leer treffen. Die Engine rückt dann um ein Zeichen weiter, mit dem Flag u/v um einen ganzen Codepunkt.
  • Kompatibilität: Wird seit ES2015 von allen aktuellen Browsern und Node.js unterstützt. Der Internet Explorer unterstützt die Methode nicht.