JavaScript中exec()方法詳解

前言:

有時(shí)候?qū)W習(xí)進(jìn)度緩慢,像一只慢爬的蝸牛,欣慰的是總歸每天在進(jìn)步,希望一切越來(lái)越好。

最近學(xué)習(xí)正則,發(fā)現(xiàn)javascript中exec()方法理解有些不容易,因此稍加整理了一下,一做分享二也希望大神看到不到之處多多指點(diǎn)。

另本文只講解exec()方法,至于正則語(yǔ)法及在js中使用請(qǐng)自行谷歌。

一、RegExp對(duì)象的聲明及exec()方法的使用

聲明一個(gè)RegExp有兩種方式:
1)var re=new RegExp(pattern,modifiers);
2)var re =/pattern/modifiers;

注釋:
pattern(模式): 描述了表達(dá)式的模式
modifiers(修飾符) 用于指定全局匹配、區(qū)分大小寫的匹配和多行匹配,具體有 i 、g 和 m 三類,這三類也可以自由組合也可以不添加修飾符。

修飾符 釋義
i 代表忽略大小寫
g 代表全局匹配
m 執(zhí)行多行匹配
示例:

1)var re=new RegExp(pattern,modifiers);

var re1=new RegExp("\\w{2}");   
var re2=new RegExp("\\w{2}","i"); 
 
2)var re =/pattern/modifiers;
var re3=/\w{2}/;
var re4=/\w{2}/ig;

使用RegExp對(duì)象的exec()方法:

直接調(diào)用即可。如果匹配到字符串返回一個(gè)數(shù)組;如果沒(méi)有匹配到返回null
1) var re1=new RegExp("\w{2}");

 var res1=re1.exec("要檢索的字符串");

2)var re3=/\w{2}/;

var res2=re3.exec("要檢索的字符串");
示例:
<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        var re1=/\d[a-zA-Z]/;   //匹配兩位一個(gè)數(shù)字和一個(gè)忽略大小寫的字母
        var res1=re1.exec('aa2edj3djie7788');
        var res2=re1.exec('458949468974484');
    </script>
</body>
</html>

我們斷點(diǎn)來(lái)看var res1=re1.exec('aa2edj3djie7788');執(zhí)行結(jié)果


匹配字符串'aa2edj3djie7788'結(jié)果斷點(diǎn).png

我們?cè)贁帱c(diǎn)看var res2=re1.exec('458949468974484');執(zhí)行結(jié)果


匹配字符串'458949468974484'結(jié)果斷點(diǎn).png

總上所知,我們使用exec()方法得到的結(jié)果有兩個(gè),一個(gè)是存有匹配字符串的數(shù)組,一個(gè)是null

二、RegExp對(duì)象和執(zhí)行exec()得到的結(jié)果分析

咳咳,這里需要?jiǎng)澫轮攸c(diǎn)。希望能仔細(xì)看下這里。
1)首先RegExp對(duì)象
只需要關(guān)系此對(duì)象的一個(gè)屬性,lastIndex ,這個(gè)屬性的值代表了 檢索字符串 開(kāi)始匹配的起始索引,依舊上代碼和斷點(diǎn)

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        var re1=/\d[a-zA-Z]/;   //匹配兩位一個(gè)數(shù)字和一個(gè)忽略大小寫的字母
        var res1=re1.exec('aa2edj3djie7788');
    </script>
</body>
</html>

我們來(lái)看斷點(diǎn)中的RegExp對(duì)象,在調(diào)用exec()方法前


調(diào)用exec()方法前RegEpx對(duì)象.png

我們看調(diào)用exec()方法后的斷點(diǎn)

調(diào)用exec()方法后RegEpx對(duì)象.png

注意,這里在調(diào)用exec()方法前后,lastIndex值雖然沒(méi)有改變,但是這個(gè)屬性至關(guān)重要。
1)lastIndex代表了每次匹配要檢索的字符串的開(kāi)始匹配的起始索引位置
2)在 修飾符使用了 g 后,此屬性是變的,因此對(duì)后面理解 g修飾符是非常關(guān)鍵的。

2)執(zhí)行exec()的到的結(jié)果
這里我們只斷點(diǎn)查看數(shù)組結(jié)果,null也沒(méi)啥好看的好像。
下面看斷點(diǎn)截圖


執(zhí)行exec()返回的數(shù)組.png

來(lái)看下數(shù)組對(duì)象每個(gè)屬性:
var a=res1[0]; // 匹配到的字符串
var index=res1.index; //匹配到的字符串的第一個(gè)字符 在被檢索字符串String中的位置
var input=res1.input; //被檢索的字符串 string
var length=res1.length; //數(shù)組的長(zhǎng)度

三、修飾符 i 的使用

修飾符 i 代表了匹配時(shí)忽略大小寫,下面上代碼吧。

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        var re1=new RegExp("\\d[a-z]");   //匹配兩位一個(gè)數(shù)字和一個(gè)忽略大小寫的字母
        var re2=new RegExp("\\d[a-z]","i");
        var res1=re1.exec('8AJDJDJ');
        var res2=re2.exec('8AJDJDJ');
    </script>
</body>
</html>

斷點(diǎn)查看 var res1=re1.exec('8AJDJDJ'); 執(zhí)行結(jié)果


沒(méi)有使用修飾符i結(jié)果.png

斷點(diǎn)查看 var res2=re2.exec('8AJDJDJ'); 執(zhí)行結(jié)果


使用修飾符i執(zhí)行結(jié)果.png

四、修飾符 g 的使用

修飾符g代表全局匹配,全局匹配就是對(duì)把整個(gè)要檢索的字符串全部 匹配一遍。

原理就是 當(dāng)使用了 g 修飾符,每次調(diào)用 exec()方法后,如果匹配到了字符串,則 lastIndex屬性的值會(huì)改變。
而沒(méi)有使用 g 修飾符,每次調(diào)用exec()方法后,lastIndex值永遠(yuǎn)都為0 ,所以每次調(diào)用exec()最多只會(huì)檢索出一個(gè)相同的字符。
至于使用了g修飾符,找到匹配的字符串后,lastIndex的值會(huì)被重置為匹配內(nèi)容的下一個(gè)字符在 需要檢索字符串 中的位置索引。

下面來(lái)上代碼和斷點(diǎn)吧,一目了然。我們一行行斷點(diǎn)來(lái)搞清楚 g 的原理。

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        
         // 使用 g 修飾符  全局搜索
         var test1=new RegExp("\\d\\w","g");
         var res1=test1.exec("1a2b3c4d5e");
         
         var res2=test1.exec("1a2b3c4d5e");

         //綜上可知, 使用g全局搜索的時(shí)候,我們可以使用循環(huán)
         do{
            var res=test1.exec("1a2b3c4d5e");
            if(res!=null){
                console.log(res[0]);
            }
            
         }while(res!=null);
        

        //沒(méi)有使用 g
        var test2=/\d{2}/;
         
        var result=test2.exec("22dhdhj33djdj44");

        var result1=test2.exec("22dhdhj33djdj44");
    </script>
</body>
</html>

斷點(diǎn)查看 var test1=new RegExp("\d\w","g");

聲明使用全局搜索RegExp對(duì)象.png

斷點(diǎn)查看 執(zhí)行一次后RegExp對(duì)象 var res1=test1.exec("1a2b3c4d5e");


執(zhí)行第一次exec()方法后斷點(diǎn)截圖.png

再執(zhí)行一次,查看斷點(diǎn) var res2=test1.exec("1a2b3c4d5e");


執(zhí)行第二次exec()方法后斷點(diǎn)截圖.png

綜上可知,在使用g全局搜索時(shí),可以根據(jù) lastIndex對(duì)整個(gè) 要檢索字符串進(jìn)行匹配。因此,我們可以使用循環(huán)來(lái)得到 要檢索字符串中所有匹配的結(jié)果。

 do{
      var res=test1.exec("1a2b3c4d5e");
      if(res!=null){
         console.log(res[0]);
      }
            
}while(res!=null);

我們來(lái)看結(jié)果吧,因?yàn)槲覀円呀?jīng)執(zhí)行了兩次,所以 lastIndex此時(shí),已經(jīng)為4,因此循環(huán)檢索匹配從 要檢索字符串的索引4開(kāi)始。


巡檢檢索得到的結(jié)果.png

下面,我們來(lái)重點(diǎn)看執(zhí)行到 結(jié)果為res[0]= 5e 時(shí)的斷點(diǎn)


此時(shí)結(jié)果為5e.png

我們來(lái)看這時(shí)候的RegExp對(duì)象
這時(shí)候可以看到lastIndex值為10,即下次匹配從索引10開(kāi)始,我們知道要檢索的字符串
“1a2b3c4d5e”的長(zhǎng)度為10,因此下一次調(diào)用結(jié)果為null。


結(jié)果為5e時(shí)RegExp對(duì)象.png

我們來(lái)看下一步,當(dāng)結(jié)果為null時(shí),斷點(diǎn)截圖

image.png

我們注意到,這時(shí)候,RegExp對(duì)象的屬性 lastIndex的值重置為0。即下一次再調(diào)用 exec()方法,會(huì)從 要檢索字符串的 0索引位置 開(kāi)始匹配

通過(guò)上述一步步斷點(diǎn),相信你已經(jīng)明白了全局搜索 g修飾符的使用原理。那么我們?cè)賮?lái)看,沒(méi)有設(shè)置 g的時(shí)候,代碼的斷點(diǎn)

看這一步,var test2=/\d{2}/; 斷點(diǎn)。剛開(kāi)始 test2的lastIndex值為0


剛開(kāi)始 test2的lastIndex值為0.png

執(zhí)行一次,var result=test2.exec("22dhdhj33djdj44"); 得到的結(jié)果為 22

執(zhí)行一次非全局搜索exec()方法.png

重點(diǎn)看此時(shí)的 test2屬性 lastIndex的值,發(fā)現(xiàn)lastIndex值還是0


非全局搜索RegExp對(duì)象.png

因?yàn)楫?dāng)非全局搜索的時(shí)候,test2不管調(diào)用幾次exec()方法 ,其屬性lastIndex值都為0。
所以,非全局搜索,每次調(diào)用exec()方法總是得到第一個(gè)相同的結(jié)果。

五、修飾符 m 的使用

修飾符m執(zhí)行多行匹配。代表多行模式multiline。

使用m時(shí)需要注意:
1)當(dāng)要檢索的字符串為單行時(shí),使用 m無(wú)意義。很明顯啊,只有一行字符串使用啥 m 啊。
2)當(dāng)要檢索的字符串有換行符 \n 或 \r\n時(shí),這里要看正則表達(dá)式有沒(méi)有位置符號(hào) ^ 和 $:

①當(dāng)正則表達(dá)式中存在 ^和$符號(hào)時(shí),使用了 m ,則:
“^”與字符串開(kāi)始位置以及“\n”或“\r”之后的位置相匹配,
“$”與字符串結(jié)束位置以及“\n”或“\r”之前的位置相匹配。

②當(dāng)正則表達(dá)式中存在 ^和$符號(hào)時(shí),沒(méi)有使用了 m ,則:
“^”與字符串的開(kāi)始位置相匹配,
“$”與字符串的結(jié)束位置相匹配。

③當(dāng)正則表達(dá)式中不存在 ^和$符號(hào)時(shí),使用了 m ,則:
正則表達(dá)式正常匹配字符串

④當(dāng)正則表達(dá)式中不存在 ^和$符號(hào)時(shí),沒(méi)有使用了 m ,則
正則表達(dá)式正常匹配字符串

下面來(lái)具體看第二條注意中各種可能。

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        
        var re=/^ad{2}$/m;
        var res=re.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");
        
        var re1=/^ad{2}$/;
        var res1=re1.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");
        
    </script>
</body>
</html>

斷點(diǎn)查看結(jié)果:

1)var res=re.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");斷點(diǎn)截圖

這是情況①
當(dāng)正則表達(dá)式中存在 ^和$符號(hào)時(shí),使用了 m ,則:
“^”與字符串開(kāi)始位置以及“\n”或“\r”之后的位置相匹配,
“$”與字符串結(jié)束位置以及“\n”或“\r”之前的位置相匹配。

m1.png

2)var res1=re1.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");斷點(diǎn)截圖

這是情況②
當(dāng)正則表達(dá)式中存在 ^和$符號(hào)時(shí),沒(méi)有使用了 m ,則:
“^”與字符串的開(kāi)始位置相匹配,
“$”與字符串的結(jié)束位置相匹配。

m2.png
<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        
        var str="fdd1727\r\naddjdsljs\r\nadd\nshshsh";
        var re=/ad{2}/m;
        var res=re.exec(str);
        
        var re1=/ad{2}/;

        var res1=re1.exec(str);
        
    </script>
</body>
</html>

斷點(diǎn)查看結(jié)果:

1)var res=re.exec(str); 斷點(diǎn)截圖

這是情況③
當(dāng)正則表達(dá)式中不存在 ^和$符號(hào)時(shí),使用了 m ,則:
正則表達(dá)式正常匹配整個(gè)要檢索的字符串

m3.png

2)var res1=re1.exec(str);

這是情況④
當(dāng)正則表達(dá)式中不存在 ^和$符號(hào)時(shí),沒(méi)有使用了 m ,則:
正則表達(dá)式正常匹配整個(gè)要檢索的字符串


m4.png

綜上所知:
使用m的時(shí)候,只有當(dāng) 要檢索的字符串中有換行符,且正則表達(dá)式中有 ^和$位置符號(hào)時(shí),m才會(huì)起作用;
其他情況下使用和不使用m都當(dāng)一個(gè)正常的字符串 匹配檢索。


后記:
至于m的使用有些特殊,有大神能夠講的更清晰和把原理能講清的還請(qǐng)不吝賜教,在此先行謝過(guò)啦。
路漫漫其修遠(yuǎn)兮,吾將上下而求索!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評(píng)論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,423評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,991評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,207評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,419評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,653評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,901評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容