Zum Hauptinhalt springen

`String.prototype.replaceAll`

· 4 Minuten Lesezeit
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Wenn Sie jemals mit Zeichenfolgen in JavaScript gearbeitet haben, sind Sie wahrscheinlich auf die Methode String#replace gestoßen. String.prototype.replace(searchValue, replacement) gibt eine Zeichenfolge zurück, bei der einige Übereinstimmungen basierend auf den angegebenen Parametern ersetzt werden:

'abc'.replace('b', '_');
// → 'a_c'

'🍏🍋🍊🍓'.replace('🍏', '🥭');
// → '🥭🍋🍊🍓'

Ein häufiger Anwendungsfall ist das Ersetzen aller Instanzen einer bestimmten Teilzeichenfolge. Allerdings berücksichtigt String#replace diesen Anwendungsfall nicht direkt. Wenn searchValue eine Zeichenfolge ist, wird nur das erste Vorkommen der Teilzeichenfolge ersetzt:

'aabbcc'.replace('b', '_');
// → 'aa_bcc'

'🍏🍏🍋🍋🍊🍊🍓🍓'.replace('🍏', '🥭');
// → '🥭🍏🍋🍋🍊🍊🍓🍓'

Um dieses Problem zu umgehen, verwandeln Entwickler die Suchzeichenfolge häufig in einen regulären Ausdruck mit dem globalen (g) Flag. Auf diese Weise ersetzt String#replace alle Übereinstimmungen:

'aabbcc'.replace(/b/g, '_');
// → 'aa__cc'

'🍏🍏🍋🍋🍊🍊🍓🍓'.replace(/🍏/g, '🥭');
// → '🥭🥭🍋🍋🍊🍊🍓🍓'

Als Entwickler ist es ärgerlich, diese Zeichenfolgen-in-Regulär-Ausdruck-Konvertierung durchführen zu müssen, wenn Sie wirklich nur eine globale Ersetzung von Teilzeichenfolgen wünschen. Noch wichtiger ist, dass diese Konvertierung fehleranfällig ist und eine häufige Fehlerquelle darstellt! Betrachten Sie das folgende Beispiel:

const queryString = 'q=query+string+parameters';

queryString.replace('+', ' ');
// → 'q=query string+parameters' ❌
// Nur das erste Vorkommen wird ersetzt.

queryString.replace(/+/, ' ');
// → SyntaxError: ungültiger regulärer Ausdruck ❌
// Es stellt sich heraus, dass `+` ein Sonderzeichen innerhalb von regulären Ausdrucksmustern ist.

queryString.replace(/\+/, ' ');
// → 'q=query string+parameters' ❌
// Das Escapen spezieller regulärer Ausdruckszeichen macht den regulären Ausdruck gültig, aber
// dies ersetzt immer noch nur das erste Vorkommen von `+` in der Zeichenfolge.

queryString.replace(/\+/g, ' ');
// → 'q=query string parameters' ✅
// Das Escapen spezieller regulärer Ausdruckszeichen UND das Verwenden des `g` Flags machen es funktional.

Eine Zeichenfolge wie '+' in einen globalen regulären Ausdruck umzuwandeln, besteht nicht nur darin, die ' Anführungszeichen zu entfernen, sie in / Schrägstriche einzukapseln und das g Flag hinzuzufügen – wir müssen alle Zeichen escapen, die in regulären Ausdrücken eine besondere Bedeutung haben. Das ist leicht zu vergessen und schwer richtig zu machen, da JavaScript keinen eingebauten Mechanismus zum Escapieren von regulären Ausdrucksmustern bietet.

Ein alternativer Workaround ist die Kombination von String#split mit Array#join:

const queryString = 'q=query+string+parameters';
queryString.split('+').join(' ');
// → 'q=query string parameters'

Dieser Ansatz vermeidet jedes Escapen, bringt jedoch den Aufwand mit sich, die Zeichenfolge in ein Array von Teilen zu zerlegen, nur um sie anschließend wieder zusammenzufügen.

Offensichtlich sind keine dieser Lösungen ideal. Wäre es nicht großartig, wenn eine grundlegende Operation wie die globale Ersetzung von Teilzeichenfolgen in JavaScript unkompliziert wäre?

String.prototype.replaceAll

Die neue Methode String#replaceAll löst diese Probleme und bietet einen unkomplizierten Mechanismus zur Durchführung der globalen Ersetzung von Teilzeichenfolgen:

'aabbcc'.replaceAll('b', '_');
// → 'aa__cc'

'🍏🍏🍋🍋🍊🍊🍓🍓'.replaceAll('🍏', '🥭');
// → '🥭🥭🍋🍋🍊🍊🍓🍓'

const queryString = 'q=query+string+parameters';
queryString.replaceAll('+', ' ');
// → 'q=query string parameters'

Um Konsistenz mit den bereits vorhandenen APIs in der Sprache zu gewährleisten, verhält sich String.prototype.replaceAll(searchValue, replacement) genauso wie String.prototype.replace(searchValue, replacement), mit den folgenden zwei Ausnahmen:

  1. Wenn searchValue eine Zeichenfolge ist, ersetzt String#replace nur das erste Vorkommen der Teilzeichenfolge, während String#replaceAll alle Vorkommen ersetzt.
  2. Wenn searchValue ein nicht-globaler regulärer Ausdruck ist, ersetzt String#replace nur eine einzelne Übereinstimmung, ähnlich wie es sich bei Zeichenfolgen verhält. String#replaceAll hingegen löst in diesem Fall eine Ausnahme aus, da dies wahrscheinlich ein Fehler ist: Wenn Sie wirklich „alle“ Übereinstimmungen ersetzen möchten, würden Sie einen globalen regulären Ausdruck verwenden; wenn Sie nur eine einzige Übereinstimmung ersetzen möchten, können Sie String#replace verwenden.

Der wichtige neue Funktionsumfang liegt im ersten Punkt. String.prototype.replaceAll bereichert JavaScript mit einer erstklassigen Unterstützung für die globale Ersetzung von Teilzeichenfolgen ohne die Notwendigkeit von regulären Ausdrücken oder anderen Umgehungsmöglichkeiten.

Eine Anmerkung zu speziellen Ersetzungsmustern

Es ist erwähnenswert: Sowohl replace als auch replaceAll unterstützen spezielle Ersetzungsmuster. Obwohl diese Muster am nützlichsten in Kombination mit regulären Ausdrücken sind, wirken einige von ihnen ($$, $&, $` , und $') auch bei einfacher Zeichenkettenersetzung, was überraschend sein kann:

'xyz'.replaceAll('y', '$$');
// → 'x$z' (nicht 'x$$z')

Falls Ihre Ersetzungszeichenfolge eines dieser Muster enthält und Sie sie unverändert verwenden möchten, können Sie das magische Substitutionsverhalten umgehen, indem Sie eine Ersetzungsfunktion verwenden, die die Zeichenfolge zurückgibt:

'xyz'.replaceAll('y', () => '$$');
// → 'x$$z'

Unterstützung für String.prototype.replaceAll