正規表現の関数でlastIndexに注意


正規表現の関数でうっかりひっかかりそうなところがあったのでメモ

検索する正規表現は /\w{3,}/ig (3文字以上の英数字の単語にマッチする、正規表現)を使う

const input = "As I was going to TDL";
const re = /\w{3,}/ig;

console.log(input.match(re)); // ['was', 'going', 'TDL'] (マッチした単語を配列に)

console.log(input.search(re)); // 5 (最初に見つかる単語は5文字目からはじまる)

ここまでは、input(文字列)のメソッドで
マッチした文字列、最初に見つかる単語を取得できるということで問題なし

正規表現のメソッドからが少しひっかかった

console.log(re.test(input)); // ture

let a = re.exec(input); // execは文字位置を記憶
console.log(a); // [ 'going', index: 9, input: 'As I was going to TDL']
console.log(a[0]); // going
console.log(a[1]); // undefined

console.log(re.exec(input)); // [ 'TDL', index: 18, input: 'As I was going to TDL']
console.log(re.exec(input)); // null (マッチするものがない)

console.log(re.exec());

変数aのとき、てっきり結果はwasかと思ってどうしてgoingが…と思ったが
正規表現でg(グローバルフラグ)が設定されている場合は、lastIndexを保持するため、
呼び出した際に、lastIndexから検索されることになった

上記のコードではマッチするものがなくなっているため、lastIndex0になるが
lastIndex18の状態で別の文字列をre.exec()でチェックすると
lastIndexからの検索となるから注意が必要になる

console.log(re.exec(input)); // [ 'TDL', index: 18, input: 'As I was going to TDL']
// console.log(re.exec(input)); // null (マッチするものがない)

console.log(re.exec('I want to play outside freely'));
// [ 'freely', index: 23, input: 'I want to play outside freely']
// freelyのfが18番目になるのでfから検索がスタートする

execを使うことはあまりなさそうだが、もし使う時がある場合はハマりそうだと思ったので注意したい