0、前言
一段代碼引發(fā)的思考:
var r = /\d/g;console.log(r.test('1'));console.log(r.test('1'));console.log(r.test('2'));console.log(r.test('2'));
先看看如上的代碼,不要執(zhí)行,自己先猜測(cè)下結(jié)果。
1、正則修飾符
正則在各個(gè)語(yǔ)言中,實(shí)現(xiàn)的標(biāo)準(zhǔn)并不完全一致。我們這里就討論在 JavaScript
中的實(shí)現(xiàn)。
在 JavaScript
中,正則有四個(gè)修飾符: global, ignoreCase, multiline, unicode
,詳細(xì)請(qǐng)參考:MDN RegExp。
它們的含義如下:
global(g) 針對(duì)字符串中所有可能的匹配來(lái)測(cè)試正則表達(dá)式
ignoreCase(i) 匹配時(shí)忽略大小寫(xiě)
multiline(m) 多行輸入將被視為多行(此時(shí)開(kāi)始^和結(jié)尾匹配$可以在每行中進(jìn)行匹配)
unicode(u) 對(duì)字符串采用unicode進(jìn)行匹配
修飾符:i
i
比較易懂,在匹配的時(shí)候會(huì)忽略大小寫(xiě),示例如下:
var text = 'abc';var r = /abc/;console.log(r.test('abc')); // trueconsole.log(r.test('Abc')); // falser = /abc/i;console.log(r.test('abc')); // trueconsole.log(r.test('Abc')); // true
修飾符:m
當(dāng)匹配多行時(shí),默認(rèn)是全文本匹配,使用 m
之后,將對(duì)每一行進(jìn)行單獨(dú)匹配。
// 定義一個(gè)多行文本var text = `a b cA B C`;var r = /c$/; // 匹配以C結(jié)尾的文本console.log(r.test(text)); // false 全文本匹配,匹配不上r = /c$/m;console.log(r.test(text)); // true 多行匹配,c是第一行的末尾,匹配成功
修飾符:u
使用修飾符 u
,將采用 Unicode
模式進(jìn)行匹配,必須要在正則中包含unicode才能看到效果:
var r = /\u{61}/; // 匹配61次u字符console.log(r.test('a')); // false, 明顯匹配不上r = /\u{61}/u; // Unicode模式,\u{61} = 'a'console.log(r.test('a')); // true, Unicode下能匹配r = /\u{61}{3}/u; // 匹配3個(gè)a,注意正則寫(xiě)法console.log(r.test('aaa')); // true
注意:在/u模式下,正則中 \u{xxx} 是一個(gè)整體,不可拆分。
2、正則修飾符:g
接下來(lái),進(jìn)入本文的重點(diǎn),修飾符 g
的匹配模式。
首先,我們先回到開(kāi)頭的那段代碼,我想大部分人的答案可能是:true true true true
吧。
實(shí)際上,正確答案是:true false true false
,是不是覺(jué)得不可思議?接著往下看。
RegExp.prototype.test()
RegExp.prototype.test()
方法的邏輯是:當(dāng)找到第一個(gè)匹配項(xiàng)時(shí),返回 true
。查找整個(gè)字符串都沒(méi)有找到匹配項(xiàng),返回 false
。
那具體又是如何查找的呢?這里我們就要看 RegExp
的另外一個(gè)方法了:RegExp.prototype.exec()
。
注意觀(guān)察這個(gè)方法的返回值:
var r = /\d/;// 注意看,返回值是一個(gè)數(shù)組,除了匹配到的元素之外,還有一個(gè) index 屬性console.log(r.exec('123')); // ["1", index: 0, input: "123"]
關(guān)鍵就是 exec
返回值中的 index
屬性,這個(gè)屬性標(biāo)識(shí)從輸入文本的哪一個(gè)索引處開(kāi)始查找匹配項(xiàng)。
如果不加 g
,每次都是從索引0處開(kāi)始查找。
var r = /\d/;console.log(r.exec('123')); // ["1", index: 0, input: "123"]console.log(r.exec('123')); // ["1", index: 0, input: "123"]console.log(r.exec('123')); // ["1", index: 0, input: "123"]
那如果加 g
呢?
var r = /\d/g;console.log(r.exec('123')); // ["1", index: 0, input: "123"]console.log(r.exec('123')); // ["2", index: 1, input: "123"]console.log(r.exec('123')); // ["3", index: 2, input: "123"]console.log(r.exec('123')); // null
從結(jié)果我們可以看出,這個(gè) index
是在變化的,當(dāng)找不到匹配項(xiàng)時(shí),會(huì)返回 null。
總結(jié)一下:修飾符 g
的作用,是標(biāo)識(shí)是否需要全局存儲(chǔ)這個(gè)index。
有了這個(gè)理解,那么回到之前的問(wèn)題,那就說(shuō)得通了。我們使用了 g
修飾符,那么會(huì)存儲(chǔ)上一次的 index
,當(dāng)執(zhí)行第二次 console.log(r.test('1'));
時(shí),索引為1,當(dāng)然就匹配不上了,所以就返回了 false
。
那問(wèn)題又來(lái)了,為什么第三次,又返回了 true
呢?
還是先看代碼:
var r = /\d/g;console.log(r.exec('12')); // ["1", index: 0, input: "12"]console.log(r.exec('12')); // ["2", index: 1, input: "12"]console.log(r.exec('12')); // nullconsole.log(r.exec('12')); // ["1", index: 0, input: "12"]
當(dāng)發(fā)現(xiàn)已經(jīng)匹配不上元素時(shí),會(huì)將這個(gè) index
重新設(shè)置為 0
。
http://www.cnblogs.com/humin/p/6927210.html