js中幾個正則表達式相關函數使用時g標誌的做用

首先,javascript中涉及到正則表達式的函數總共有6個,可分爲兩種:javascript

一、第一種是做爲字符串對象的方法,即以html

String.fun();

形式調用,這裏包括 split、search、match、replace 這四個函數。java

二、第二種是做爲正則表達式對象的方法,即以正則表達式

RegExp.fun();

形式調用,這裏包括 exec、test 這兩個函數。c#

 

咱們知道,正則表達式從結構上劃分的話能夠簡單的劃分爲三部分:分隔符、表達式 和 標誌符。數組

如正則表達式函數

/^abc$/is

中,先後兩個斜槓就是分隔符,分隔符中間的內容爲表達式,第二個分隔符後的is就是標誌符。測試

本文重點討論g標誌符在js的幾個正則表達式相關函數中的做用。g標誌符是正則表達式標誌符中點擊率較高的一個標誌符,其做用爲讓該正則表達式進行全局匹配。spa

何時該進行全局匹配,何時不應進行全局匹配,哪些函數支持全局匹配標誌g,哪些函數又不支持?手冊上沒有清楚的講述這些瑣碎的知識點,那就動手寫測試代碼,讓程序說話。code

1)split:將一個字符串分割爲子字符串,而後將結果做爲字符串數組返回。

<script>
var p = /ab/,
    pg = /ab/g,
    str = 'abcabcabc';

// split 函數
var a = str.split(p);
console.log(a); // ['','c','c','c']
console.log(p.lastIndex); // 0
var ag = str.split(pg);
console.log(ag); // ['','c','c','c']
console.log(pg.lastIndex); // 0
</script>

能夠看到使用g標誌和不使用g標誌的結果如出一轍,因此能夠認爲g標誌在split函數中是無心義的。

2)search:返回與正則表達式查找內容匹配的第一個子字符串的位置。

<script>
var p = /ab/,
    pg = /ab/g,
    str = 'abcabcabc';

// search 函數
a = str.search(p);
console.log(a); // 0,'ab'字符串第一次出現的位置
console.log(p.lastIndex); // 0
ag = str.search(pg);
console.log(ag); // 0,'ab'字符串第一次出現的位置
console.log(pg.lastIndex); // 0
</script>

能夠看到使用g標誌和不使用g標誌的結果如出一轍,因此能夠認爲g標誌在search函數中是無心義的。

3)match:使用正則表達式模式對字符串執行查找,並將包含查找的結果做爲數組返回。

<script>
var p = /ab/,
    pg = /ab/g,
    str = 'abcabcabc';

// match 函數
a = str.match(p);
console.log(a); // ['ab'],若是沒有設置全局標誌g,數組的0元素包含整個匹配,而第 1 到 n 元素包含了匹配中曾出現過的任一個子匹配。
console.log(p.lastIndex); // 0
ag = str.match(pg);
console.log(ag); // ["ab", "ab", "ab"],這塊手冊上說的很清楚,當正則含有g標誌時,全局查找,結果數組的元素0到n中包含全部匹配。
console.log(pg.lastIndex); // 0
</script>

能夠看到對於match函數,使用g標誌和不使用g標誌差異很大。好在手冊中對其說明也比較詳細。

4)replace:返回根據正則表達式進行文字替換後的字符串的複製。

<script>
var p = /ab/,
    pg = /ab/g,
    str = 'abcabcabc';

// replace 函數
a = str.replace(p,'#');
console.log(a); // #cabcabc
console.log(p.lastIndex); // 0
ag = str.replace(pg,'#'); 
console.log(ag); // #c#c#c
console.log(pg.lastIndex); // 0
</script>

能夠看到有g標誌跟沒g標誌的結果徹底不一樣,沒有g標誌的狀況下只替換第一個匹配項。

5)exec:用正則表達式模式在字符串中運行查找,並返回包含該查找結果的一個數組。

<script>
var p = /ab/,
    pg = /ab/g,
    str = 'abcabcabc';

// exec 函數
a = p.exec(str);
console.log(a); // ['ab']
console.log(p.lastIndex); // 0
ag = pg.exec(str);
console.log(ag); // ['ab']
console.log(pg.lastIndex); // 2
</script>

exec函數手冊上也說的很清楚,若是爲正則表達式設置了全局標誌,exec 從以 lastIndex 的值指示的位置開始查找。若是沒有設置全局標誌,exec 忽略 lastIndex 的值,從字符串的起始位置開始搜索。每次查找返回一個數組,數組元素除了0,1,2 ...外還包含3個屬性 input、index 和 lastIndex。Input 屬性包含了整個被查找的字符串。Index 屬性中包含了整個被查找字符串中被匹配的子字符串的位置。LastIndex 屬性中包含了匹配中最後一個字符的下一個位置。

6)test:返回一個 Boolean 值,它指出在被查找的字符串中是否存在模式。

<script>
var p = /ab/,
    pg = /ab/g,
    str = 'abcabcabc';

// test 函數
a = p.test(str);
console.log(a); // true 
console.log(p.lastIndex); // 0
ag = pg.test(str);
console.log(ag); // true 
console.log(pg.lastIndex); // 2
</script>

test函數在有g標誌時查找從正則表達式對象的lastIndex屬性值(此例中該處爲0)開始查找,找到一個匹配的串之後更新lastIndex屬性值,若是查找完整個串都沒找到匹配項,設置lastIndex屬性值爲0。

 

綜上,能夠看出,六個函數中只有split和search使用或者不使用g標誌結果都同樣。而其餘四個函數都有影響,其中test函數影響最小,只是影響lastIndex屬性的值,但這點正好會致使一些很難察覺的問題,好比

<script>
var pg = /ab/g,
    str = 'abc';

a = pg.test(str);
console.log(a); // true 
a = pg.test(str);
console.log(a); // false 

</script>

一樣的代碼第一次結果爲true,第二次結果爲false,緣由就是g標誌改變了lastIndesx屬性的值,而帶g標誌的test查找時又依靠lastIndex。

好了,就這些了,有總結的不對的地方,還請指正。

相關文章
相關標籤/搜索