Signatur
Beschreibung
lastIndex ist eine eigene Dateneigenschaft jeder RegExp-Instanz. Sie liegt also direkt auf dem Objekt, nicht auf dem Prototyp, und ist beschreibbar, aber nicht aufzählbar und nicht konfigurierbar. Beim Erzeugen eines regulären Ausdrucks steht sie auf 0. Ausgewertet wird sie nur, wenn der Ausdruck das Flag g (global) oder y (sticky) trägt. Ohne diese Flags beginnt die Suche immer bei Index 0, und lastIndex bleibt unverändert.
So verhalten sich RegExp.prototype.exec() und RegExp.prototype.test() bei gesetztem g oder y:
- Die Suche beginnt an der Position
lastIndex. - Bei einem Treffer wird
lastIndexauf den Index direkt nach dem Treffer gesetzt. - Gibt es keinen Treffer oder ist
lastIndexgrößer als die Länge der Zeichenkette, wirdlastIndexauf0zurückgesetzt, und die Methode liefertnullbzw.false. - Mit dem Flag
ymuss der Treffer genau beilastIndexbeginnen. Die Suche springt nicht weiter nach vorn.
In der Praxis braucht man lastIndex vor allem für zwei Dinge: um in einer Schleife alle Treffer schrittweise mit exec() abzuarbeiten und um mit dem Flag y Tokenizer oder Parser zu bauen, die gezielt an einer bestimmten Position weiterlesen. Da der Zustand im RegExp-Objekt selbst gespeichert wird, führt ein wiederverwendeter globaler Ausdruck schnell zu schwer auffindbaren Fehlern (siehe Hinweise).
Rückgabewert
ToLength in eine ganze Zahl umgewandelt.Beispiele
Alle Treffer mit exec() und lastIndex durchlaufen
const re = /\d+/g;
const text = 'Artikel 12, Menge 7, Preis 199';
let match;
while ((match = re.exec(text)) !== null) {
console.log(`${match[0]} gefunden bei ${match.index}, lastIndex jetzt ${re.lastIndex}`);
}
console.log('Nach der Schleife:', re.lastIndex);
Fallstrick: test() mit globalem Ausdruck liefert abwechselnd true/false
const istZahl = /^\d+$/g;
console.log(istZahl.test('42'), istZahl.lastIndex);
console.log(istZahl.test('42'), istZahl.lastIndex); // Suche beginnt bei 2!
// Abhilfe: g-Flag weglassen oder lastIndex zurücksetzen
istZahl.lastIndex = 0;
console.log(istZahl.test('42'));
Einfacher Tokenizer mit Sticky-Flag y
const tokenize = (input) => {
const regeln = [
['ZAHL', /\d+/y],
['OP', /[+\-*\/]/y],
['LEER', /\s+/y],
];
const tokens = [];
let pos = 0;
while (pos < input.length) {
let treffer = false;
for (const [typ, re] of regeln) {
re.lastIndex = pos; // exakt an der aktuellen Position prüfen
const m = re.exec(input);
if (m) {
if (typ !== 'LEER') tokens.push({ typ, wert: m[0] });
pos = re.lastIndex;
treffer = true;
break;
}
}
if (!treffer) throw new SyntaxError(`Unerwartetes Zeichen bei ${pos}`);
}
return tokens;
};
console.log(tokenize('12 + 3*4'));
Suche gezielt ab einer Position starten
const re = /ab/g;
const s = 'ab--ab--ab';
re.lastIndex = 3;
const m = re.exec(s);
console.log(m.index, re.lastIndex);
// Wichtig · Fallstricke
- Zustandsbehaftete Ausdrücke: Ein RegExp-Literal mit
godery, das in einer Konstanten auf Modulebene steht und mehrfach mittest()oderexec()benutzt wird, merkt sichlastIndexüber alle Aufrufe hinweg. Dadurch liefert es abwechselndtrueundfalse. Für reine Ja/Nein-Prüfungen lässt man dasg-Flag daher weg. - Leere Treffer: Passt ein Muster auf eine leere Zeichenkette (z. B.
/a*/g), bleibtlastIndexbei einer eigenenexec()-Schleife stehen, und die Schleife läuft endlos. In diesem Fall muss manre.lastIndex++selbst hochzählen oder gleichmatchAll()verwenden. String.prototype.match()mitg,replace(),replaceAll()undsplit()setzenlastIndexvorher intern auf0.matchAll()arbeitet auf einer Kopie des Ausdrucks und verändert das Original nicht.String.prototype.search()ignoriertlastIndexund stellt den ursprünglichen Wert danach wieder her.- Mit dem Flag
uodervzähltlastIndexweiterhin in UTF-16-Codeeinheiten, nicht in Unicode-Codepunkten. - Die Eigenschaft wird von allen Browsern und von Node.js unterstützt. Das Flag
ygibt es seit ES2015.