跳至內容
Astera Technology

同一 regex 再測一次,為何結果不同?

同一個全域 regex 重複測試,要把 lastIndex 一起看。

下載完整個案資料及參考答案 ↓

先追這段程式

用 /^[a-z]+$/g 測 markup 兩次,重設 lastIndex 後再測。文字沒有變,regex 的狀態卻已不同。

完整原始程式
const pattern=/^[a-z]+$/g;const results=[];
results.push(pattern.test('markup'));results.push(pattern.test('markup'));
pattern.lastIndex=0;results.push(pattern.test('markup'));
console.log(JSON.stringify(results));
確實的 console 輸出
[true,false,true]
值與執行位置
測試真假結果lastIndex afterward
first markuptrue6
second markupfalse0
重設後再測 markuptrue6

結果為何如此

全域 regex 從 lastIndex 開始,成功後會更新。第二次由 6 開始,配合 ^ 起點要求便失敗,並重設為零。這種固定整段文字驗證可不用 g,避免帶狀態。y 也使用 lastIndex,但搜尋規則另有不同。

比較另一種寫法

本例全域模式不適合反覆無狀態驗證。修正為非全域後,同一有效字串兩次都通過;大寫邊界仍不符這個模式。

另開的有限例子
const pattern=/^[a-z]+$/;console.log(JSON.stringify([pattern.test('markup'),pattern.test('markup'),pattern.test('Markup')]));
另一寫法的輸出
[true,true,false]

試清邊界

lastIndex=0 會否改變模式容許的字元?

查看參考答案

不會,只改開始位置。模式仍要求一個或以上小寫 ASCII 字母,沒有其他字元。

重新建立的邊界例子
const pattern=/^[a-z]+$/g;const trace=[];for(const value of ['markup','markup','']){trace.push({value,ok:pattern.test(value),lastIndex:pattern.lastIndex});}
console.log(JSON.stringify(trace));
邊界例子的輸出
[{"value":"markup","ok":true,"lastIndex":6},{"value":"markup","ok":false,"lastIndex":0},{"value":"","ok":false,"lastIndex":0}]

原始例子檔案