循環下的正則匹配?說說正則中的lastIndex

最近在使用正則匹配的時候,我遇到一個很是有意思的現象,代碼以下所示: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,而是交替打印truefalse值,這究竟是爲何? 爲了查清楚究竟是怎麼回事,我開始上網搜索相關資料,通過一番搜索後,發現正則並無咱們想象的那麼簡單...spa


what's going on?

首先正則有一個屬性叫lastIndex,它表示正則下一次匹配時的起始位置。通常狀況下咱們是使用不到它的,但在正則中包含全局標誌g時,正則的testexec方法就會使用到它,具體規則以下:code

  • 初始狀態下lastIndex的值爲0
  • 若成功匹配,lastIndex的值就被更新成被匹配字符串後面的第一個字符的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。以此類推,最終以909的形式交替打印。

而第二個實驗因爲咱們增長了部分字符串的長度,所以對於第二、4個字符串而言,即便從第9個字符開始匹配,依然能匹配到後邊的.jpg,故lastIndex繼續更新到13

經過此次小小的實驗,咱們發現使用正則的時候仍是要多加當心,對於testexec方法,最好仍是不要隨意加上全局標誌g

相關文章
相關標籤/搜索