var reg1 = /^1$/g;
var reg2 = /^1$/;
for (var i = 0; i < 10; i++) {
console.log(reg1.test('1')) // true false true false true false true false ...
console.log(/^1$/g.test('1')) // true true true true true true true ...
console.log(reg2.test('1')) // true true true true true true true ...
console.log(/^1$/.test('1')) // true true true true true true true ...
}
為什麼第一條console.log的輸出會是這樣?
正規執行時, RegExp物件的lastIndex可能會改變.
test 方法用於偵測字串是否符合某個正規規則, 只要是字串中含有與正規規則相符的文字, 該方法就傳回true, 否則傳回 false.
實際上, 如果正規表示式帶有全域標誌(帶有參數g)時, test 方法還受正規物件的lastIndex屬性影響,如下:
該影響將在exec 方法講解中予以分析.
exec 方法用於偵測字串對正規表示式的符合, 如果找到了符合的文字, 則傳回一個結果陣列, 否則傳回null.
語法: exec(string)
exec 方法傳回的陣列中包含兩個額外的屬性, index 和 input. 並且該陣列具有以下特點:
第 0 項表示正規表示式捕獲的文字
第 1~n 項表示第 1~n 個反向引用, 依序指向第 1~n 個分組捕獲的文本, 可以使用RegExp.$ + "編號1~n" 依次獲取分組中的文本
index 表示匹配字串的初始位置
input 表示正在檢索的字串
無論正規表示式有無全域標示"g", exec 的表現都相同. 但正規表示式物件的表現卻有些不同. 下面我們來詳細說明下正規表示式物件的表現都有哪些不同.
假設正規表示式物件為 reg , 偵測的字元為 string , reg.exec(string) 傳回值為 array.
若reg 包含全域標示"g", 那麼reg.lastIndex 屬性表示原字串中匹配的字串末尾的後一個位置, 即下次匹配開始的位置, 此時reg.lastIndex == array.index(匹配開始的位置) + array[0].length(匹配字串的長度). 如下:
隨著檢索繼續, array.index 的值將往後遞增, 也就是說, reg.lastIndex 的值也會同步往後遞增. 因此, 我們也可以透過反覆呼叫exec 方法來遍歷字串中所有的匹配文字. 直到exec 方法再也匹配不到文字時, 它將傳回null, 並把reg.lastIndex 屬性重設為0.
接著上述例子, 我們繼續執行程式碼, 看看上面說的對不對, 如下所示:
以上程式碼中, 隨著重複呼叫 exec 方法, reg.lastIndex 屬性最終被重設為 0.
問題回顧
在test 方法的講解中, 我們留下了一個問題. 如果正則表達式帶有全局標誌g, 以上test 方法的執行結果將受reg.lastIndex影響, 不僅如此, exec 方法也一樣. 由於reg.lastIndex的值並不總是為零, 並且它決定了下次匹配開始的位置, 如果在一個字符串中完成了一次匹配之後要開始檢索新的字符串, 那就必須要手動地把lastIndex 屬性重置為0. 避免以下這種錯誤:
以上程式碼, 正確執行結果應該是 "123456", 因此建議在第二次執行 exec 方法前, 增加一句 "reg.lastIndex = 0;".
若 reg 不包含全域標示"g", 則 exec 方法的執行結果(array)將與 string.match(reg) 方法執行結果完全相同.
該片段來自 正規表示式前端使用手冊 | louis blog 有幫助的話請按讚吧~