依次寫出下列輸出內(nèi)容。
var reg1 = /a/;
var reg2 = /a/g;
console.log(reg1.test('abcabc')); // true
console.log(reg1.test('abcabc')); // true
console.log(reg1.test('abcabc')); // true
console.log(reg1.test('abcabc')); // true
console.log(reg2.test('abcabc')); // true
console.log(reg2.test('abcabc')); // true
console.log(reg2.test('abcabc')); // false
console.log(reg2.test('abcabc')); // true
很簡單的一個(gè)正則表達(dá)式測(cè)試,查找字符串a(chǎn)bcabc中是否有字符a。但是結(jié)果卻有一個(gè)特殊false存在,Why?
lastIndex(針對(duì)于帶參數(shù)g的正則表達(dá)式)
在每個(gè)實(shí)例化的RegExp對(duì)象中,都存在一個(gè)lastIndex屬性,其初始值為0。
/a/.lastIndex // 0
new RegExp('a').lastIndex // 0
lastIndex表示匹配成功時(shí)候,匹配內(nèi)容最后一個(gè)字符所在原字符串中的位置 + 1,也就是匹配內(nèi)容的下一個(gè)字符的index(如果匹配內(nèi)容在字符串的結(jié)尾,同樣返回原字符串中的位置 + 1,也就是字符串的length)。如果未帶參數(shù)g,lastIndex始終為0。
var reg = /ab/g;
reg.test('123abc');
console.log(reg.lastIndex) // 5
// 匹配內(nèi)容在最后
var reg = /ab/g;
reg.test('123ab');
console.log(reg.lastIndex) // 5
// 不帶參數(shù)g
var reg = /ab/;
reg.test('123abc');
console.log(reg.lastIndex) // 0
而這個(gè)lastIndex也就是用該正則進(jìn)行其他匹配操作的時(shí)候匹配開始的位置。而匹配失敗時(shí)重置lastIndex為0。
var reg = /ab/g;
// 初始值為0,從最開始匹配 匹配成功, lastIndex為4
console.log(reg.test('12ab34ab'), reg.lastIndex); // true 4
// 從第4位字符"3"開始匹配 匹配內(nèi)容為第二個(gè)ab lastIndex 為 8
console.log(reg.test('12ab34ab'), reg.lastIndex); // true 8
// 從第8位 (字符長度為8,沒有第8位) 開始匹配 匹配不成功 重置lastIndex 為 0
console.log(reg.test('12ab34ab'), reg.lastIndex); // false 0
// 從頭匹配 同第一步
console.log(reg.test('12ab34ab'), reg.lastIndex); // true 4
看到這里題目也就解答完畢,接下來是擴(kuò)展。
對(duì)于未重新聲明的reg容易犯錯(cuò)的地方。
// 測(cè)試字符串str1 和 str2 是否都含有ab字符
var reg = /ab/g;
var str1 = '123ab';
var str2 = 'ab123';
console.log(reg.test(str1)); // true
console.log(reg.test(str2)); // false
很明顯這里因?yàn)閘astIndex的原因?qū)е屡袛噱e(cuò)誤。這里可以修改reg不帶參數(shù)g或則重新聲明reg,當(dāng)然也可以在第一次匹配后手動(dòng)修改reg.lastIndex = 0。
預(yù)查
接著說預(yù)查,字面意思就是預(yù)備匹配查詢,也就是查詢匹配內(nèi)容接下來的內(nèi)容,但是只是預(yù)備查詢匹配,并不返回。
經(jīng)常我們需要匹配到字符串中某些字符后面跟某些字符,但是我們不需要匹配結(jié)果中包含后面跟的字符,例如:
找出下面字符串中字符后面是2的所有字符。
var str = 'a1b2c22d31e4fg6h2';
'a1b2c22d31e4fg6h2'.match(/[a-z]2/g); // ["b2", "c2", "h2"]
這樣,雖然能匹配出字符串帶2的,但是數(shù)字2我們并不需要,這里只需要字符。而用預(yù)查:
'a1b2c22d31e4fg6h2'.match(/[a-z](?=2)/g); // ["b", "c", "h"]
可以看到完全滿足條件,但是預(yù)查和本文的主題lastIndex又有幾毛錢的關(guān)系呢?
我們用test來看看,至于為什么用test這里要說明一下,match是匹配所有,直到匹配不成功的時(shí)候結(jié)束匹配,而匹配不成功時(shí),lastIndex就被重置為0了。
而exec和test是第一次匹配成功或者匹配失敗就返回,并不會(huì)接著往下匹配。
var reg1 = /[a-z](?=2)/g;
var reg2 = /[a-z]2/g;
var str = 'a1b2c22d31e4fg6h2';
console.log(reg1.test(str), reg1.lastIndex); // true 3
console.log(reg1.test(str), reg1.lastIndex); // true 5
console.log(reg1.test(str), reg1.lastIndex); // true 16
console.log(reg1.test(str), reg1.lastIndex); // false 0
console.log(reg2.test(str), reg2.lastIndex); // true 4
console.log(reg2.test(str), reg2.lastIndex); // true 6
console.log(reg2.test(str), reg2.lastIndex); // true 17
console.log(reg2.test(str), reg2.lastIndex); // false 0
看出問題沒有?預(yù)查的lastIndex不包含預(yù)查內(nèi)容! 這里就可以用來簡化很多判斷了。
例如我們要匹配密碼必須有至少一個(gè)大寫字母,一個(gè)小寫字母,一個(gè)數(shù)字,并且長度至少6位而且只能是數(shù)字字母組合。
按照不會(huì)預(yù)查的情況會(huì)這樣去判斷:
/[a-z]/.test(pwd) /[A-Z]/.test(pwd) /\d/.test(pwd) /^[a-zA-Z0-9]{6,}$/.test(pwd);
但是:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z0-9]{6,}$/.test(pwd)
分解出來看:
(?=.*[a-z]) 是否有小寫字母 但是是預(yù)查 匹配失敗返回false 成功lastIndex不變動(dòng),還是為0,同理理解兩外預(yù)查內(nèi)容,最后就是6喂以上的字母數(shù)字組合匹配,但是前面都是預(yù)查,lastIndex始終未0,每次匹配都是從最開始匹配的,所以滿足要求。
以上所述是小編給大家介紹的淺析正則表達(dá)式中的lastIndex以及預(yù)查,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
您可能感興趣的文章:- JS中正則表達(dá)式要注意lastIndex屬性
- js正則表達(dá)式之RegExp對(duì)象屬性lastIndex,lastMatch,lastParen,lastContext,rightContext屬性講解
- Javascript lastIndex 正則表達(dá)式的一個(gè)疑惑
- 淺析lastIndex對(duì)正則表達(dá)式結(jié)果的影響