🦍
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を使うのをお勧めします。