最近在使用正則匹配的時候,我遇到一個很是有意思的現象,代碼以下所示:javascript
const reg = /\.jpg/g;
const arr = [
'test1.jpg',
'test2.jpg',
'test3.jpg',
'test4.jpg',
'test5.jpg',
];
arr.map(item => console.log(reg.test(item)));
複製代碼
這段代碼很好理解:它的規則就是判斷字符串中是否含有.jpg
,而後再循環地和數組中的字符串進行匹配,打印出結果。java
很顯然這很是之簡單嘛,輸出的結果固然是全爲true
啦~數組
然而,圖樣圖森破,它的結果是這樣的:ui
代碼的執行結果很是神奇:它並無所有打印true
,而是交替打印true
和false
值,這究竟是爲何? 爲了查清楚究竟是怎麼回事,我開始上網搜索相關資料,通過一番搜索後,發現正則並無咱們想象的那麼簡單...spa
首先正則有一個屬性叫lastIndex
,它表示正則下一次匹配時的起始位置。通常狀況下咱們是使用不到它的,但在正則中包含全局標誌g
時,正則的test
和exec
方法就會使用到它,具體規則以下:code
lastIndex
的值爲0lastIndex
的值就被更新成被匹配字符串後面的第一個字符的index,或者可理解爲被匹配字符串的最後一個字符index + 1,lastIndex
則被重置爲0。lastIndex
的位置開始進行爲驗證這個結論,我特地作了兩個實驗:regexp
第一個就是直接將正則的lastIndex
打印出來:cdn
const reg = /\.jpg/g;
const arr = [
'test1.jpg',
'test2.jpg',
'test3.jpg',
'test4.jpg',
'test5.jpg',
];
arr.map(item => console.log(reg.test(item), reg.lastIndex));
複製代碼
第二個就對數組中的字符串稍做修改:blog
const reg = /\.jpg/g;
const arr = [
'test1.jpg',
'longTest4.jpg',
'test3.jpg',
'longTest4.jpg',
'test5.jpg',
];
arr.map(item => console.log(reg.test(item), reg.lastIndex));
複製代碼
經過兩組實驗的對比觀察,發現確實如此:ip
在第一個實驗中,因爲數組中字符串的長度都是一致的,成功匹配後lastIndex
的值直接更新爲9,下次匹配的時候直接從第10個字符開始(很明顯根本就沒第10個字符嘛),所以匹配失敗,lastIndex
重置爲0。以此類推,最終以9
、0
、9
的形式交替打印。
而第二個實驗因爲咱們增長了部分字符串的長度,所以對於第二、4個字符串而言,即便從第9個字符開始匹配,依然能匹配到後邊的.jpg
,故lastIndex
繼續更新到13
經過此次小小的實驗,咱們發現使用正則的時候仍是要多加當心,對於test
和exec
方法,最好仍是不要隨意加上全局標誌g
。