RegExp: lastIndex
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Die lastIndex
Daten-Eigenschaft einer RegExp
Instanz gibt den Index an, an dem die nächste Übereinstimmung beginnen soll.
Probieren Sie es aus
const regex1 = new RegExp("foo", "g");
const str1 = "table football, foosball";
regex1.test(str1);
console.log(regex1.lastIndex);
// Expected output: 9
regex1.test(str1);
console.log(regex1.lastIndex);
// Expected output: 19
Wert
Eine nicht-negative ganze Zahl.
Eigenschaften von RegExp: lastIndex | |
---|---|
Schreibbar | ja |
Aufzählbar | nein |
Konfigurierbar | nein |
Beschreibung
Diese Eigenschaft wird nur gesetzt, wenn die reguläre Ausdrucksinstanz das g
-Flag für eine globale Suche oder das y
-Flag für eine sticky Suche verwendet. Die folgenden Regeln gelten, wenn exec()
für eine gegebene Eingabe aufgerufen wird:
- Wenn
lastIndex
größer ist als die Länge der Eingabe, findetexec()
keine Übereinstimmung undlastIndex
wird auf 0 gesetzt. - Wenn
lastIndex
gleich oder kleiner ist als die Länge der Eingabe, versuchtexec()
, die Eingabe ablastIndex
zu matchen.- Wenn
exec()
eine Übereinstimmung findet, wirdlastIndex
auf die Position des Endes des gefundenen Strings in der Eingabe gesetzt. - Wenn
exec()
keine Übereinstimmung findet, wirdlastIndex
auf 0 gesetzt.
- Wenn
Andere regexbezogene Methoden, wie RegExp.prototype.test()
, String.prototype.match()
, String.prototype.replace()
, etc., rufen exec()
intern auf, daher haben sie unterschiedliche Auswirkungen auf lastIndex
. Siehe deren jeweilige Seiten für Details.
Beispiele
Verwendung von lastIndex
Betrachten Sie die folgende Abfolge von Befehlen:
const re = /(hi)?/g;
Matched den leeren String.
console.log(re.exec("hi"));
console.log(re.lastIndex);
Gibt ["hi", "hi"]
zurück mit lastIndex
, gleich 2.
console.log(re.exec("hi"));
console.log(re.lastIndex);
Gibt ["", undefined]
zurück, ein leeres Array, dessen nulltes Element der gefundene String ist. In diesem Fall der leere String, weil lastIndex
2 war (und immer noch 2 ist) und hi
die Länge 2 hat.
Verwendung von lastIndex mit sticky Regexen
Die lastIndex
Eigenschaft ist beschreibbar. Sie können sie setzen, um den regulären Ausdruck seine nächste Suche an einem bestimmten Index beginnen zu lassen.
Das y
-Flag erfordert fast immer das Setzen von lastIndex
. Es matched immer strikt bei lastIndex
und versucht nicht, spätere Positionen zu finden. Dies ist meist nützlich für das Schreiben von Parsern, wenn Sie Tokens nur an der aktuellen Position matchen möchten.
const stringPattern = /"[^"]*"/y;
const input = `const message = "Hello world";`;
stringPattern.lastIndex = 6;
console.log(stringPattern.exec(input)); // null
stringPattern.lastIndex = 16;
console.log(stringPattern.exec(input)); // ['"Hello world"']
Zurücksetzen von lastIndex
Auch das g
-Flag profitiert vom Setzen von lastIndex
. Ein häufiger Anwendungsfall ist, wenn der String in der Mitte einer globalen Suche modifiziert wird. In diesem Fall können wir eine bestimmte Übereinstimmung verpassen, wenn der String verkürzt wird. Wir können dies vermeiden, indem wir lastIndex
zurücksetzen.
const mdLinkPattern = /\[[^[\]]+\]\((?<link>[^()\s]+)\)/dg;
function resolveMDLink(line) {
let match;
let modifiedLine = line;
while ((match = mdLinkPattern.exec(modifiedLine))) {
const originalLink = match.groups.link;
const resolvedLink = originalLink.replaceAll(/^files|\/index\.md$/g, "");
modifiedLine =
modifiedLine.slice(0, match.indices.groups.link[0]) +
resolvedLink +
modifiedLine.slice(match.indices.groups.link[1]);
// Rewind the pattern to the end of the resolved link
mdLinkPattern.lastIndex += resolvedLink.length - originalLink.length;
}
return modifiedLine;
}
console.log(
resolveMDLink(
"[`lastIndex`](files/en-us/web/javascript/reference/global_objects/regexp/lastindex/index.md)",
),
); // [`lastIndex`](/en-us/web/javascript/reference/global_objects/regexp/lastindex)
console.log(
resolveMDLink(
"[`ServiceWorker`](files/en-us/web/api/serviceworker/index.md) and [`SharedWorker`](files/en-us/web/api/sharedworker/index.md)",
),
); // [`ServiceWorker`](/en-us/web/api/serviceworker) and [`SharedWorker`](/en-us/web/api/sharedworker)
Versuchen Sie, die Zeile mdLinkPattern.lastIndex += resolvedLink.length - originalLink.length
zu löschen und das zweite Beispiel auszuführen. Sie werden feststellen, dass der zweite Link nicht korrekt ersetzt wird, weil lastIndex
nach der Verkürzung des Strings bereits über dem Index des Links liegt.
Warnung: Dieses Beispiel dient nur zur Demonstration. Zur Verarbeitung von Markdown sollten Sie wahrscheinlich stattdessen eine Parser-Bibliothek verwenden.
Optimierung der Suche
Sie können die Suche optimieren, indem Sie lastIndex
auf einen Punkt setzen, an dem vorherige mögliche Vorkommen ignoriert werden können. Zum Beispiel anstelle von:
const stringPattern = /"[^"]*"/g;
const input = `const message = "Hello " + "world";`;
// Pretend we've already dealt with the previous parts of the string
let offset = 26;
const remainingInput = input.slice(offset);
const nextString = stringPattern.exec(remainingInput);
console.log(nextString[0]); // "world"
offset += nextString.index + nextString.length;
Betrachten Sie dies:
stringPattern.lastIndex = offset;
const nextString = stringPattern.exec(remainingInput);
console.log(nextString[0]); // "world"
offset = stringPattern.lastIndex;
Dies ist potenziell effizienter, da wir das String-Slicing vermeiden.
Vermeidung von Nebenwirkungen
Die durch exec()
verursachten Nebenwirkungen können verwirrend sein, insbesondere wenn die Eingabe bei jedem exec()
unterschiedlich ist.
const re = /foo/g;
console.log(re.test("foo bar")); // true
console.log(re.test("foo baz")); // false, because lastIndex is non-zero
Dies ist noch verwirrender, wenn Sie lastIndex
von Hand modifizieren. Um die Nebenwirkungen einzudämmen, denken Sie daran, lastIndex
zurückzusetzen, nachdem jede Eingabe vollständig verarbeitet wurde.
const re = /foo/g;
console.log(re.test("foo bar")); // true
re.lastIndex = 0;
console.log(re.test("foo baz")); // true
Mit etwas Abstraktion können Sie erfordern, dass lastIndex
vor jedem exec()
-Aufruf auf einen bestimmten Wert gesetzt wird.
function createMatcher(pattern) {
// Create a copy, so that the original regex is never updated
const regex = new RegExp(pattern, "g");
return (input, offset) => {
regex.lastIndex = offset;
return regex.exec(input);
};
}
const matchFoo = createMatcher(/foo/);
console.log(matchFoo("foo bar", 0)[0]); // "foo"
console.log(matchFoo("foo baz", 0)[0]); // "foo"
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # sec-properties-of-regexp-instances |