Start · Sprachen · JavaScript · Referenz · RegExp[Symbol.species]

RegExp[Symbol.species]

Eigenschaft

Statischer Getter, der den Konstruktor liefert, mit dem <code>RegExp</code>-Methoden wie <code>[Symbol.split]()</code> und <code>[Symbol.matchAll]()</code> interne Kopien eines regulären Ausdrucks erzeugen.

seit JavaScript ES2015 Kategorie: method-property

Signatur

get RegExp[Symbol.species]

Beschreibung

RegExp[Symbol.species] ist eine statische Zugriffseigenschaft (Getter) des RegExp-Konstruktors. Die Standardimplementierung gibt einfach this zurück, also den Konstruktor, über den die Eigenschaft abgefragt wird. Bei RegExp selbst ist das RegExp, bei einer Unterklasse class MyRegExp extends RegExp {} dagegen MyRegExp.

Gebraucht wird der Wert intern von Methoden, die eine Kopie des regulären Ausdrucks anlegen müssen, bevor sie arbeiten können:

  • RegExp.prototype[Symbol.split](), aufgerufen von String.prototype.split(). Die Kopie bekommt zusätzlich das Flag y (sticky).
  • RegExp.prototype[Symbol.matchAll](), aufgerufen von String.prototype.matchAll(). Die Kopie bekommt eine eigene lastIndex-Position, damit das Original nicht verändert wird.

Beide Methoden ermitteln den Konstruktor über die abstrakte Operation SpeciesConstructor. Sie lesen zuerst regex.constructor und dann dessen [Symbol.species]. Über einen eigenen statischen Getter kann eine Unterklasse also festlegen, dass diese internen Kopien als einfache RegExp-Objekte entstehen und nicht als Instanzen der Unterklasse. Das ist sinnvoll, wenn der Konstruktor der Unterklasse Nebenwirkungen hat (Protokollierung, Prüfungen) oder eine andere Parameterliste erwartet.

Für den Alltag ist die Eigenschaft selten wichtig. Relevant wird sie, wenn Sie RegExp ableiten und steuern wollen, wie sich die Unterklasse bei split() und matchAll() verhält.

Rückgabewert

Typ
Function
Beschreibung
Den Wert von this, also den Konstruktor, über den die Eigenschaft abgefragt wurde (RegExp oder eine Unterklasse). Mit einem eigenen Getter kann eine Unterklasse einen anderen Konstruktor zurückgeben.

Beispiele

Standardwert bei RegExp und Unterklassen

class MyRegExp extends RegExp {}

console.log(RegExp[Symbol.species] === RegExp);
console.log(MyRegExp[Symbol.species] === MyRegExp);

// Der Getter ist auf RegExp definiert und wird vererbt
const desc = Object.getOwnPropertyDescriptor(RegExp, Symbol.species);
console.log(typeof desc.get, desc.set);
true true function undefined

split() erzeugt intern eine Kopie über species

class LoggingRegExp extends RegExp {
  constructor(...args) {
    super(...args);
    console.log(`Neue Instanz: /${this.source}/${this.flags}`);
  }
}

const sep = new LoggingRegExp('-');
const teile = 'a-b-c'.split(sep);
console.log(teile);
Neue Instanz: /-/ Neue Instanz: /-/y [ 'a', 'b', 'c' ]

species überschreiben: interne Kopien als normales RegExp

class Tracked extends RegExp {
  constructor(...args) {
    super(...args);
    console.log(`Tracked erstellt: /${this.source}/${this.flags}`);
  }

  // Interne Kopien sollen keine Tracked-Instanzen sein
  static get [Symbol.species]() {
    return RegExp;
  }
}

const re = new Tracked('\\d', 'g');
const zahlen = [...'a1b2c3'.matchAll(re)].map((m) => m[0]);
console.log(zahlen);
console.log(re.lastIndex); // Original bleibt unverändert
Tracked erstellt: /\d/g [ '1', '2', '3' ] 0

// Wichtig · Fallstricke

  • Nur split und matchAll: match(), replace(), search(), test() und exec() legen keine Kopie an und lesen Symbol.species nicht.
  • Umweg über constructor: Zuerst wird regex.constructor gelesen. Ist das undefined, wird RegExp verwendet. Ist es kein Objekt, gibt es einen TypeError. Ist [Symbol.species] undefined oder null, wird ebenfalls RegExp verwendet.
  • Kein Setter: Eine einfache Zuweisung wie MyRegExp[Symbol.species] = RegExp hat keine Wirkung (im Strict Mode gibt es einen TypeError). Überschreiben Sie den Wert mit einem static get [Symbol.species]() oder mit Object.defineProperty().
  • Kopien werden aufgerufen: Der species-Konstruktor wird mit (regex, flags) aufgerufen. Erwartet der Konstruktor Ihrer Unterklasse eine andere Parameterliste, gibt es Fehler. Geben Sie dann RegExp als species zurück.
  • Leistung: Wenn RegExp oder RegExp.prototype verändert wird, etwa beim globalen Überschreiben von Symbol.species, schalten Engines wie V8 ihre schnellen Pfade für reguläre Ausdrücke ab. Ändern Sie den Wert nur in Unterklassen, niemals direkt an RegExp.
  • Kompatibilität: Wird von allen modernen Browsern und Node.js 6.5+ unterstützt (Baseline), nicht vom Internet Explorer. Es gibt Diskussionen im TC39, Symbol.species langfristig einzuschränken. Neuer Code sollte sich deshalb möglichst nicht darauf stützen.