🦍
JavaScriptの正規表現でgフラグを使う際は気をつけた方が良い
はじめに
先日こちらのツイートが流れてきました。
動画内では次のことをやっていました。
何が起きているのか、まったくわからなかったので気になってこの挙動について調べて備忘録として残します。
> const r = /boop/g
undefined
> r.test("boop")
true
> r.test("boop")
false
> r.test("boop")
true
> r.test("boop")
false
>
gフラグとは
JavaScriptを書いている方は一度くらいは/foo/g
みたいな正規表現を書いたことがあるかと思います。
このg
フラグをつけることで文字列内のすべてのfoo
が対象になります。
たとばfoobarfoo
の場合/foo/
だと先頭のfoo
のみが対象になりますがg
フラグを使うとbar
のあとにfoo
も対象になります。
詳細はMDNを参照して下さい。
lastIndex
とは
JavaScriptの正規表現オブジェクトにはlastIndex
というプロパティがあり、g
またはy
フラグが有効の場合に使われます。
このプロパティはRegexp.exec()
が一致する文字列を見つけた場合、その文字列の末尾の位置に設定されます。
一致する文字列が見つからなかった場合は0が設定されます。
冒頭の動画の挙動はこのlastIndex
が関係していました。
1回目の検索ではboop
を見つけられたのでlatestIndex
が4に設定されます。
2回目の検索ではlastIndex
の位置から始まるが、対象文字列が見つからないためlastIndex
が0に設定されます。
これが繰り返されるといった感じです。
> const r = /boop/g
undefined
> r.lastIndex
0
> r.test("boop")
true
> r.lastIndex
4
> r.test("boop")
false
> r.lastIndex
0
>
さいごに
JavaScriptなにもわからない。
Discussion
RegExp.prototype.exec
やRegRxp.prototype.test
を使う場合に注意が必要な仕様ですね。今ですとg
フラグを使う場合は ES2020String.prototype.matchAll
を使うのをお勧めします。