このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docsコミュニティーについてもっと知り、仲間になるにはこちらから。
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 2015年7月.
lastIndex はRegExp インスタンスのデータプロパティで、次の照合を開始する位置を指定します。
In this article
試してみましょう
const regex = /foo/g;const str = "table football, foosball";regex.test(str);console.log(regex.lastIndex);// 予想される結果: 9regex.test(str);console.log(regex.lastIndex);// 予想される結果: 19値
非負の整数です。
RegExp: lastIndex のプロパティ属性 | |
|---|---|
| 書込可能 | 可 |
| 列挙可能 | 不可 |
| 設定可能 | 不可 |
解説
このプロパティは、正規表現インスタンスがグローバル検索を示すためにg フラグを使用した場合、または粘着的検索を示すためにy フラグを使用した場合にのみ設定されます。exec() が指定された入力に対して呼び出されたとき、以下の規則が適用されます。
lastIndexが入力の長さよりも大きい場合、exec()は一致するものを見つけられず、lastIndexは 0 に設定されます。lastIndexが入力の長さ以下であった場合、exec()はlastIndexから一致するものを探そうとします。exec()が一致するものを見つけた場合lastIndexは入力の中の一致する文字列の末尾の位置に設定されます。exec()が一致するものを見つけられなかった場合、lastIndexは 0 に設定されます。
他の正規表現関連のメソッド、RegExp.prototype.test()、String.prototype.match()、String.prototype.replace() などはexec() を呼び出しので、lastIndex における影響は異なります。詳細はそれぞれのページを参照してください。
例
>lastIndex の使用
例えば、以下の一連の処理を考えてみてください。
const re = /(hi)?/g;空文字列に一致します。
console.log(re.exec("hi"));console.log(re.lastIndex);["hi", "hi"] を返し、lastIndex は 2 になります。
console.log(re.exec("hi"));console.log(re.lastIndex);返値は["", undefined] で、 0 番目の要素が一致文字列となる空の配列です。この場合、lastIndex が 2 (現在も 2) であり、hi の長さが 2 であるため、空の文字列となります。
lastIndex を sticky の正規表現で使用
lastIndex プロパティは書き込み可能です。これを設定することで、正規表現が指定したインデックスから次の検索を開始するようになります。
y フラグはほとんどの場合lastIndex を設定する必要があります。これは常にlastIndex ちょうどの位置で照合し、それ以降の位置では照合を試みません。これは通常パーサーを書くときに、現在の位置のトークンのみに一致させたい場合に便利です。
const stringPattern = /"[^"]*"/y;const input = `const message = "Hello world";`;stringPattern.lastIndex = 6;console.log(stringPattern.exec(input)); // nullstringPattern.lastIndex = 16;console.log(stringPattern.exec(input)); // ['"Hello world"']lastIndex の巻き戻し
g フラグもlastIndex を設定することで恩恵を受けることができます。よくある使用例として、グローバル検索の途中で文字列が変更された場合があります。この場合、文字列が短くなると特定の一致を見逃してしまう可能性があります。この場合はlastIndex を巻き戻すことで回避できます。
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/ja/web/javascript/reference/global_objects/regexp/lastindex/index.md)", ),); // [`lastIndex`](/ja/web/javascript/reference/global_objects/regexp/lastindex)console.log( resolveMDLink( "[`ServiceWorker`](files/ja/web/api/serviceworker/index.md) and [`SharedWorker`](files/ja/web/api/sharedworker/index.md)", ),); // [`ServiceWorker`](/ja/web/api/serviceworker) and [`SharedWorker`](/ja/web/api/sharedworker)mdLinkPattern.lastIndex += resolvedLink.length - originalLink.length の行を削除して、2 番目の例を実行してみてください。文字列が短縮された後、lastIndex が既にリンクのインデックスを過ぎているため、2 番目のリンクが正しく置換されないことがわかります。
警告:この例はデモ専用のためのものです。Markdown を扱うには、正規表現の代わりに構文解析ライブラリーを使用してください。
検索の最適化
以前の出現を無視できるポイントにlastIndex を設定することで、検索を最適化することができます。例えば、この代わりに、
const stringPattern = /"[^"]*"/g;const input = `const message = "Hello " + "world";`;// 文字列の前の部分はすでに処理したことにするlet offset = 26;const remainingInput = input.slice(offset);const nextString = stringPattern.exec(remainingInput);console.log(nextString[0]); // "world"offset += nextString.index + nextString.length;次のように考えてみてください。
stringPattern.lastIndex = offset;const nextString = stringPattern.exec(remainingInput);console.log(nextString[0]); // "world"offset = stringPattern.lastIndex;これは、文字列のスライスを避けるようになるので、より性能が高まる可能性があります。
副作用の回避
それぞれのexec() の実行毎に入力が異なる場合、exec() によって発生する副作用が混乱を招きかねません。
const re = /foo/g;console.log(re.test("foo bar")); // trueconsole.log(re.test("foo baz")); // false。lastIndex がゼロではないためこれはlastIndex を手で変更する場合にはさらに混乱します。副作用を収めるために、各入力が完全に処理された後にlastIndex をリセットすることを忘れないでください。
const re = /foo/g;console.log(re.test("foo bar")); // truere.lastIndex = 0;console.log(re.test("foo baz")); // true抽象化すれば、exec() を呼び出す前にlastIndex に具体的な値を設定するように要求することができます。
function createMatcher(pattern) { // コピーを作成し、元の正規表現が更新されないようする 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"仕様書
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-properties-of-regexp-instances> |