【愣錘筆記】一支穿雲箭、正則來相見

有人說,一行正則抵得上100行代碼……javascript

正則表達式,每門語言都有,在咱們的js開發中,最多見的使用場景:一是表單驗證,像是登陸註冊啊,用戶輸入檢測啊,無論在前臺項目仍是後臺管理系統,都會常用;二是,在開發一些重數據交互的後臺管理系統或者應用的時候,更是會大量的使用,各類字符匹配,表達式檢測等等。html

正則自己知識點不是不少,可是因爲各類字符意思容易忘記,因此須要常常複習,多使用就記住了。java

建立一個正則表達式:

// 經過RegExp構造函數建立
var regex1 = new RegExp('[a-z]', 'g');
// 經過直接字面量建立
var regex2 = /[a-z]/g;複製代碼

這兩種方式均可以建立正則表達式,以上兩種方式建立了一個等價的正則表達式,均爲匹配字母a到z。可是平常開發中,基本都是經過直接字面量建立:兩個反斜槓之間爲正則表達式,反斜槓後面跟着修飾符i、g、m。修飾符可寫可不寫,也能夠同時寫多個,他們的意思分別是:ajax

i:表示忽略大小寫,就是在字符串匹配的時候不區分大小寫。
g:表示全局匹配,即全部知足的字符都會被匹配到,一直匹配到字符串的結尾。
m:表示進行多行匹配。這個是什麼意思呢,舉個例子吧:

var str = 'hello world \n my name is LengChui.'複製代碼

可看到這個字符串中有一個\n換行符,正常匹配時,到\n就結束了,也就是隻會匹配到這一行的結尾。可是若是加了m修飾符,會繼續日後面匹配,一直匹配到字符串的最終結尾。正則表達式

固然了,修飾符能夠同時寫多個,例如:var regex = /[a-z]/ig;表示匹配全部的字母a到z,且不區分大小寫。這樣,對於字符串'a123H'就會匹配到a和Zspring


正則表達式方法:test()和exec()

全部的正則表達式都有test和exec這兩個方法。數組

test()方法:測試字符串中是否包含了匹配該正則表達式的子串,若是包含了這樣的子串,那麼返回true,不然返回falsebash

// 定義一個匹配hello字符串的正則表達式
var reg = /hello/g;
var str = 'hello world';
// 若是字符串str中匹配到了hello字符串,則打印以下信息
if (reg.test(str)) {
    console.log('字符串str中含有hello子串')
}複製代碼

這個方法相信在驗證用戶輸入內容的時候,會常用到。例如,相信不少人寫過相似下面的正則驗證用戶輸入值的合法性代碼:函數

// 點擊提交按鈕,驗證輸入值,提交ajax請求
document.getElementById('submitButton').addEventListener('click', function (event) {
    // 獲取用戶輸入的手機號
    var phoneNumber = document.getElementById('phone');
    // 驗證手機號格式的正則
    var regPhone = /^1[3|4|5|8]\d{9}$/g;
    // 檢測輸入的合法性,進行錯誤提示
    if (!phoneNumber) {
        $tim('請輸入手機號!')
        return;
    }
    if (!regPhone.test(phoneNumber)) {
        $tip('手機號格式不正確,請從新輸入!');
        return;
    }
    // 若是驗證成功,提交ajax請求
    $.ajax(………………)
}, false);複製代碼


exec方法:接收一個參數,即待檢測的字符串。它返回一個加強的數組對象,數組的第一項爲匹配到的字符串。若是正則表達式中含有子表達式,那麼該數組後續的項依次爲匹配到的第一個子表達式的匹配結果,第二個……第n個。若是沒有匹配到任何內容,則返回null。測試

經過例子來講明exec的使用方法:

// 定義一個字符串
var str = 'hello javascript, hello javaspring'
// 定義一個正則表達式,該表達式匹配任意java後跟任意大小寫字母的字符串
// 注意這裏的正則表達式沒有加g,後面會說明exec的正則表達式加g與不加g的區別
var reg = /java([a-zA-Z]+)/;
// 調用exec方法
var execResult = reg.exec(str);
console.log(execResult)複製代碼

看下最終的打印結果:


能夠看到返回一個數組,數組的第一項爲匹配到的結果,第二項爲第一個子表達式的匹配結果,若是還有其餘子表達式,會依次日後排。同時這個數組對象還有如下幾個屬性:

  1. groups: undefined
  2. index// 當前匹配結果的開始下標。這裏匹配的javascript字符串的開始下標爲6。
  3. input // 待匹配的字符串,其實就是咱們的這裏的str字符串

注意上述正則表達式/java([a-zA-Z]+)/沒有加修飾符g,這意味着不須要全局匹配。這種狀況下,exec()方法只會匹配依次便最終匹配結束了,那麼若是繼續調用execResult = reg.exec(str);,則會從新開始匹配,即從字符串0的位置開始從新匹配並返回新的匹配結果。其結果確定是同樣的。以下面例子:

var str = 'hello javascript, hello javaspring'
var reg = /java([a-zA-Z]+)/;
// 第一次匹配調用並打印結果
var execResult = reg.exec(str);
console.log(execResult);
// 從新調用並打印結果
execResult = reg.exec(str);
console.log(execResult);複製代碼


能夠看到兩次調用的匹配結果是同樣的。這裏不由就有人說了,那不是廢話了,調用同一個表達式,結果不就同樣嘛。然而,還真不是。在介紹這個以前,咱們先簡單提一下正則表達式的實例屬性,告訴了咱們該正則表達式的一些基本信息。這個不須要記,瞭解一下便可:

var reg2 = /a/igm; // 定義一個不區分大小寫、全局匹配、多行匹配字符串a的正則表達式
console.dir(reg2) // 打印出該對象複製代碼


下表中列出了全部的正則表達式實例屬性。

實例屬性 含義
global Boolean值,指明正則表達式是否包含g修飾符
ignoreCase Boolean值,指明正則表達式是否包含i修飾符
lastIndex
若正則表達式包含 g 修飾符,該屬性指明執行 exec() test() 方法後,最後一次匹配結果字符串後面的第一個字符的位置
source 只讀屬性,給出了正則表達式的內容,即除了斜槓和選項字符以外的整個正則表達式。
multiline Boolean值,指定搜索字符串時是否跨行搜索,便是否包含m修飾符,該屬性的另一個名稱是$*

瞭解了這個以後,咱們回過頭來繼續說exec()方法。在調用exec()方法的正則表達式沒有加修飾符g,即不是全局匹配的模式下,每次調用exec()以後,本次的正則匹配也就最終結束了,注意是最終結束了。下次該正則表達式再次調用exec()方法時會從字符串開頭開始匹配,能夠當即爲開始了一次新的正則匹配。

那麼若是調用exec()方法的正則表達式是全局匹配的話(加了修飾符g),該正則表達式每次調用exec()方法結束後,其實例屬性lastIndex都會指向本次匹配結果字符串後面一個字符的位置,直到匹配結果返回null,即沒有匹配到任何結果的時候,纔會將其lastIndex屬性重置爲0。繼續看這個例子演示:

var str = 'hello javascript, hello javaspring'
// 定義匹配任何java後跟任意大小寫字母的字符串,注意這裏是全局匹配
var reg = /java([a-zA-Z]+)/g;

// 該正則表達式第一次調用exec()方法並打印匹配結果和其實例屬性lastIndex
var execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);

// 第二次調用
execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);

// 第三次調用
execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);複製代碼


從打印結果能夠看出,第一次匹配到了字符串javascript,其開始下標爲6,實例屬性lastIndex16,即javascript字符串後面的一個字符「逗號」的位置下標。第二次調用的匹配結果爲javaspringlastIndex的值爲34。第三次調用沒有匹配到任何結果,因此返回了null,其lastIndex的結果也被重置爲了0

關於正則方法exec()有一點必需要提,很容易致使錯誤的狀況。當調用exec()方法的正則表達式是全局匹配的狀況下,對一個字符串匹配後,若是沒有匹配到最終結果,即沒有返回null的狀況下,使用該正則表達式對新字符串進行exec()方法調用時,切記必定要先將該正則表達式的實例屬性lastIndex重置爲0。看例子:

var str = 'hello javascript, hello javaspring'
var str2 = 'javascript and html'

// 定義匹配任何java後跟任意大小寫字母的正則表達式,全局匹配
var reg = /java([a-zA-Z]+)/g;

// 使用該正則的exec()方法匹配字符串str
var execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);

// 使用該正則的ecev()方法匹配字符串str2
execResult = reg.exec(str2);
console.log(execResult, reg.lastIndex);複製代碼


從打印結果能夠看出,對於str字符串的正則匹配時,正常返回告終果,其lastIndex的值爲16,還並無最終匹配結束,lastIndex值也沒有重置爲0。這時候直接使用該正則表達式對str2進行exec()方法調用,卻返回了null。爲何呢,正常應該也能夠匹配到str2字符的javascript字符啊。這是由於,對str調用後,其lastIndex值被賦值爲了16,那麼下次對str2調用的時候,便從下標16開始調用,str2中從下標16開始匹配天然而然是沒有匹配到任何字符串。注意,正則表達式的實例屬性lastIndex是可讀可寫的屬性,因此爲了不這種狀況,在對str2正則匹配前,先將其lastIndex屬性重置爲0

reg.lastIndex = 0;
execResult = reg.exec(str2);
console.log(execResult, reg.lastIndex);複製代碼


元字符

所謂元字符,其實就是在正則表達式的不一樣上下文中有着特殊意義的標點符號,請看下面:

. * + ( ) $ / \ ? [ ] ^ { } - ! < >       複製代碼

嗯~沒錯,就是這幾個字符,經過不一樣的組合能夠幫咱們構建出很是強大的正則表達式。注意,這些字符帶有特殊意義,若是就只是單純的項匹配這些字符,須要加/進行轉義,例如\.就只是匹配一個點,沒有其餘特殊意義。下面咱們一一進行介紹。

. : 匹配除了換行符和回車以外的任何字符,eg: /./ 匹配一個除換行回車以外的任意字符;

[] :  匹配方括號裏面的任意字符。方括號內能夠是1個字符也能夠是多個字符。eg: [ab] 匹配字符a,也能夠匹配字符b;[a- z] 能夠匹配字母a到z任意一個,-表示的意思;[0-9]能夠匹配數字0到9;也能夠混合使用[a-zA-Z0-9]能夠匹配小寫字母a到z,大寫字母A-Z,能夠匹配數字0-9;

[^] : 匹配除了方括號內^後面的任意字符,能夠理解爲[]的取反操做。eg: /[^ab]/ 匹配除了a和b之外的任意字符。 

| : 或,即匹配 | 左邊或者右邊的表達式。eg: /a|b/ 匹配字符a或者字符b

: 匹配0個或多個前面的表達式, eg: /a*/ 匹配0或者多個a,a、aa、aaa、aaaa等都是知足匹配規則的。

+ : 匹配1個或多個前面的表達式,和*相似,可是至少要知足匹配一次。eg: /a+/ 能夠匹配1個或多個a,隱藏a、aa、aaa等都是合法的,可是bcdf是不符合匹配規則的,由於沒有至少匹配到一個a。

? :  匹配0和或1個前面的表達式,能夠理解爲前一項是可選的。和*+相似,可是要注意三者的區別。

{n, m} : 匹配前一項n到m次,包含n次和m次。eg: /[0-9]{6,8}/ 能夠匹配6到8位數字。

{n, } :  匹配前一項至少n次。 eg: /[0-9]{11, }/ 至少匹配11位數字

{n} : 匹配前一項n次。 eg: /[0-9]{5}/  匹配5位數字

須要注意的是:*?能夠匹配前一項0次,所以像相似 /a*/.test('bcdf') 是返回true的,由於他匹配到了0個a;而/a*/.exec('bcdf')也是返回了一個第一項是一個空字符串的數組,而不是返回null,也是由於匹配了0個a。

另外一個須要注意的是,正則匹配默認都是貪婪匹配。什麼意思呢?就是儘量多的匹配,好比用/a+/來匹配字符串aaabbbb時,會匹配到aaa,即儘量多匹配。相似的重複匹配時都是貪婪匹配的。然而可使用這些元字符加上?的形式來取消貪婪匹配,即儘量的少匹配。如/a+?/再對aaabbbb匹配時,則只會匹配到一個a,其餘的*?  {}? ??同理。

\ : 和一些字符組合使用會有特殊的意義:

\w 元符號,等價於[a-zA-Z0-9_],匹配任何字母、數字、下劃線字符,這樣的字符也稱爲單詞字符
\W 元符號,等價於[^a-zA-Z0-9_],匹配除了字母、數字、下劃線字符以外的任何字符
\d 元符號,等價於[0-9],匹配任何單個的數字字符
\D 元符號,等價於[^0-9],匹配除了數字以外的任何單個字符
\s 元符號,匹配空白字符,即空格、Tab字符和回車換行符
\S 元字符,匹配任何非空白字符

^ :匹配字符串的開始位置,或多行匹配模式中(即加了修飾符m)每一行的開始位置

$ : 匹配字符串的結束位置,或多行匹配模式下(即加了修飾符m)每一行的結束位置

^$這兩個元字符,在平常開發中幾乎是最多見的了,幾乎大部分的正則表達式都是這種形式的:/^表達式$/。都知道是它的意思是匹配字符串的開始和結束爲止,猛一看好像理解了,可是細細揣摩貌似又不知道究竟是什麼意思。下面我就細細說來:

這兩個字符和上面其餘元字符不一樣的是,這個字符匹配的是位置,而不是具體匹配的某個字符。這麼說,應該清晰一點了,因此/^表達式$/就是從字符串開頭的位置開始,一直到結束的位置,都必須知足匹配規則才行。再次強調下,^$匹配的都只是一個位置,位置,位置。

\b : 匹配單詞邊界。這個也是用來匹配位置的,通俗的講,就是匹配區分單詞分割位置的。例如,兩個單詞之間的位置,第一個單詞前面的位置,最後一個單詞後面的位置,都是匹配的單詞位置。eg: /\bjava\b/能夠匹配單詞java,即匹配java字符兩邊都是單詞邊界的結果,對於字符串I love java very much則匹配成功,而字符串I love javascript very much則匹配不成功。由於第一句的java兩邊空格都是單詞邊界,而javascipt雖然包含了java單詞,可是隻知足左邊是單詞邊界,其子串java的右邊是script子串,而不是單詞邊界,因此不知足兩邊都是單詞邊界的匹配規則。

console.log(/\bjava\b/.test('java')) // true
console.log(/\bjava\b/.test('javascript')) // false複製代碼

\B:匹配非單詞邊界,是\b的反義詞。eg:/\Bscript/ 對於字符串javascript是能夠匹配成功的,由於其子串script的左側是java字符串,不是單詞邊界。而對於字符串script則是不成功的,由於其左側什麼都沒有,即左側就是一個單詞邊界。

console.log(/\Bscript/.test('javascript')) // true
console.log(/\Bscript/.test('script')) // false複製代碼


斷言

js裏面的斷言只支持先行斷言,又分爲正向先行斷言負向先行斷言。這麼說比較繞口,讓人云裏霧裏的感受,因此仍是直接上例子:

?= : 正向先行斷言,其實就是說?=左邊的內容後面,必須跟着?=右邊的內容。通常使用方式爲:x(?=y),意思是字符x後面必須是字符y。eg:/java(?=script)/ 只能匹配javascript,不能匹配javaspring,java123等等。

?! : 負向先行斷言,即?!左邊的內容後面必定不能跟?!右邊的內容。通常使用方式爲: x(?!y),意思是字符x後面必定不能是字符串y。eg:/java(?=script)/ 只能匹配javaspring,java123等等,但不能匹配javascript。


分組/子表達式

() : 子表達式,也能夠叫分組,就是把括號裏面的表達式做爲一個總體來處理。一個正則表達式裏面能夠有多個子表達式,子表達式裏面也能夠嵌套子表達式。在咱們介紹exec()方法的時候說過,exec()返回一個加強的數組,數組第一項爲該正則表達式的匹配結果,第二項及之後爲對應的子表達式的匹配結果。

// 沒有子表達式的正則exec()方法
var reg1 = /[a-z][0-9]/;
var str1 = 'hello123';
console.log(reg1.exec(str1))

// 添加了子表達式的正則exec()方法		
var reg2 = /([a-z])([0-9])/;
var str2 = 'hello123';
console.log(reg2.exec(str2))

// 子表達式嵌套的狀況
var reg3 = /(([a-z])([0-9]))/;
var str3 = 'hello123';
console.log(reg3.exec(str3))
複製代碼


打印結果能夠看出,加子表達式以後,比沒加以前多返回了幾項,這幾項分別對應每一個子表達式匹配的結果。注意,當有嵌套的狀況下,子表達式的順序,其實就是全部的左括號從左到右出現的順序。

每一子表達式匹配到的值都會被保存下來,分別存在\1,\2,\3……裏面,也會保存在$1,$2,$3……二者的區別是,\1這種類型的是使用在正則表達式中的,$1這種類型的是使用在字符串的方法中。關於字符串方面會在文章後面的內容講解。先看個例子吧:

// 須要匹配第一第二位都是數字,第三位和第一位必須相同,第四位和第二位必須相同的正則表達式
var reg4 = /(\d)(\d)\1\2/;
// 打印爲true,因第一位和第二位都是數字,第三位和第一的值相同,第四位和第二位的值也相同
console.log(reg4.test('1212')) // true
// 打印結果爲false,由於第三位的值和第一位的不同
console.log(reg4.test('1232'))
複製代碼

從這正則表達式能夠看到,要求匹配的第一位和第二位都是數字,那麼後面的\1和\2是什麼意思呢,就是說\1就是第一個(\d)匹配到的結果,\2就是第二個(\d)匹配到的結果。注意,這裏的意思並非說第三位第四位是和第一第二位匹配的規則相同的,而是說,加入第一位匹配到了數字2,那麼第三位也只能數字2,若是第二位匹配到了數字4,那麼第四位也必須是4才能夠。那麼最終的匹配結果就是相似1212, 4747等。eg: 左引號和右引號必須相匹配的狀況,能夠這樣子:/['"][^'"]*\1/,即首先是單引號或者雙引號,後面是0到多個非單引號雙引號字符,最後若是第一個匹配了單引號則最後一個必須是單引號,若是第一個匹配到了雙引號則最後也必須是雙引號。

注意在子表達式嵌套的狀況下,\1,\2……對應的其實就是左括號的值,無論它怎麼嵌套。這麼說應該更好理解了。

那麼問題來了,若是不想保存子表達式的值呢,或者說多個子表達式中我不想保存某些子表達式的值怎麼辦呢?

(?:)  : 一個問號加一個冒號,成爲無記憶匹配。他依然是對括號中裏面的內容進行分組,可是不會捕獲子模式,即不會保存匹配到的值到\1,\2,\3……中。如今我修改一下上面的例子再看:

// 須要匹配第一第二位都是數字,第三位和第二位必須相同
var reg4 = /(?:\d)(\d)\1/;
// 打印爲false,因第一位和第二位都是數字,第三位和第二位的值不同
console.log(reg4.test('1212'))
// 打印結果爲true,由於第三位的值和第二位的值相同
console.log(reg4.test('1232'))複製代碼

從表達式能夠看出,咱們的第一個(?:\d)子表達式添加了無記憶匹配模式,因此後面的\1裏面存放的值就變成了後面的(\d)匹配的結果。所以,子表達式設置了無記憶匹配模式後,\1,\2……便不會再存儲其匹配結果了,而是存儲後面沒有設置無記憶匹配模式的子表達式。


字符串方法中正則表達式的運用

字符串方法小夥伴們都很熟悉,這裏只說和正則匹配相關的方法。正則表達式自己就是用來處理字符串的匹配規則,那麼相應的字符串方法,固然得和正則勾搭點關係啦~~好了,拉回正題,下面先列舉和正則有關的字符串方法:

match(regex) 返回全部與正則表達式regex相匹配的子串數組
replace(regex,replacement) 字符串替換。將字符串中的regex指定的子串替換爲子串replacement
search(regex) 字符串搜索。查找正則表達式regex指定的模式在字符串中的開始位置
split(regex) 字符串分割。使用正則表達式regex分割字符串,並將分割的結果以數組的形式返回

  (1) match方法:返回一個由匹配結果組成的數組,若是沒有匹配到任何結果則返回null。該方法接收一個正則表達式做爲參數,若是不是正則表達式,它會首先調用new RegExp()將參數轉換成正則表達式。

注意:若是正則參數不帶修飾符g,match方法不會進行全局匹配,其效果和不加修飾符g的exec()方法返回的結果是同樣的。若是忘記了exec()方法,能夠往回翻翻回顧一下。

'aaaa'.match('b') // 返回null,由於沒有匹配到任何內容複製代碼

下面看下正則表達式不帶修飾符g的例子:

console.log('abcd?'.match(/a/)) 複製代碼


在不是全局匹配的狀況下,其返回結果和exec()方法一模一樣,若是表達式含有子表達式的話,數組的第二項及後續項是子表達式的匹配結果。若是是全局匹配的話,則會返回一個由全部匹配結果組成的數組:

// 不含有子表達式的全局匹配
console.log('1a2b3c4d5?'.match(/[0-9]/g))

// 含有子表達式的全局匹配
console.log('1a2b3c4d5?'.match(/[0-9]|(a)/g))複製代碼


結果很是的直觀,在全局匹配模式下會返回全部匹配結果組成的數組。可是若是正則表達式含有子表達式的話,也會把子表達式的匹配結果返回出來。

  (2) replace()方法:用於字符串的替換,並返回替換後的結果。接收兩個參數,第一個參數是匹配的規則,第二參數是用來替換的字符串。第一個參數,能夠是字符串,也能夠是正則表達式。

字符串就很少說了,這裏只說是正則表達式的狀況,replace會根據正則表達式去匹配對應的結果,而後將其替換成第二參數:

// 正則表達式不帶修飾符g
console.log('abc1234'.replace(/[a-z]/, '0'))
// 正則表達式帶修飾符g
console.log('abc1234'.replace(/[a-z]/g, '0'))複製代碼


輸出結果能夠看出,在不加修飾符g的狀況下,字符串的repalce方法不會全局檢索替換,而只是替換了第一次。在全局匹配模式下,replace方法會把全部的匹配結果全局替換成第二個參數對應的字符串。

前文說子表達式的時候說到,正則表達式會把匹配結果存放在相似\1,\2$1,$2的裏面,在這裏即可以用到$1,$2了。用法就是,在repealce()方法的第二個參數字符串中,$1,$2……再也不是普通的字符串,而是有着特殊同樣的標識符,對應的值就是正則表達式每個子表達式匹配到的結果:

// 定義一個匹配一個abc字符後面跟着一個數字的正則表達式
// 並將匹配結果替換成該子表達式的結果
console.log('abc1234'.replace(/abc(\d)/g, '$1')) // 1234複製代碼

該替換方法,最終將abc1替換成了第一個子表達式匹配的結果1,因此最終結果是1234。

repalce()方法的第二次參數,不只能夠是字符串,還能夠是一個函數,若是是函數則對每一次的匹配結果調用該函數。該函數必須返回一個字符串,若是沒有reutrn語句,則是跟正常函數同樣默認返回undefined。若是返回的不是字符串類型,會將其轉換成字符串類型:

console.log('abc1234'.replace(/abc(\d)/g, function(){ 
    return 'hello'
}))
// 打印結果爲hello234複製代碼

從結果能夠看出,將匹配到的字符串abc1替換成了hello字符串。

同時,該函數有多個參數,第一個參數是當前匹配到的結果,第二個參數開始日後是子表達式匹配到的結果,能夠有0-n個。再後面一個參數當前匹配結果在原字符串中的下標,最後一個參數原字符串:

'abc1234'.replace(/abc(\d)(\d)/g, function(a,b,c,d,f){
    console.log(a,b,c,d,f)
})
// 打印結果爲 abc12 1 2 0 abc1234複製代碼

能夠看到打印的結果abc12是正則匹配到的結果,1是第一個子表達式(\d)匹配的結果,2是第二個子表達式(\d)匹配到的結果,0是匹配結果字符串在原字符串中的下標,abc1234是原字符串。再看下匹配到屢次結果的狀況:

'abc1234abc567'.replace(/abc(\d)(\d)/g, function(a,b,c,d,f){ 
    console.log(a,b,c,d,f)
})
// 下面是打印結果
abc12 1 2 0 abc1234abc567
abc56 5 6 7 abc1234abc567複製代碼

對於有屢次匹配結果的狀況,會屢次調用該函數。

  (3) search()方法查找匹配結果在原字符串中的位置。接收一個字符串或者正則表達式做爲查詢參數。最終返回查詢到的下標,沒有查詢到則返回-1。

// 參數爲字符串時
console.log('abcd'.search('d')) // 3

// 參數爲正則表達式
console.log('abcd'.search(/d/)) // 3複製代碼

上面演示了簡單的查找,對於簡單的查找,徹底是可使用字符串的indexOf()方法,查找結果都是同樣的。

console.log('abcd'.indexOf('d')) // 3複製代碼

須要注意的地方就是:1.該方法不會進行全局查找,即會忽略修飾符g,一旦匹配到結果即返回下標; 2.會忽略正則表達式的lastIndex屬性,即每次查找都從字符串開始位置從新開始。

var str = 'abcddadd'
// 只返回了第一個d字符的洗標,忽略修飾符g
console.log(str.search(/d/g)) // 依舊輸出了3

// 第二次調用,依舊輸出3,即忽略了lastIndex屬性
console.log(str.search(/d/g))複製代碼

  (4) split()方法: 用於字符串分割,接收一個用於分割字符串的字符串或者正則表達式做爲參數,第二個參數爲可選的指定返回分割後的數組長度。

// 第一個參數爲''時, 將按字符分割字符串
// 這在咱們須要把字符串做爲組數處理時很是有用
'asdfg'.split('') // ['a', 's', 'd', 'f', 'g']
// 能夠接收第二參數,做爲返回後的數組長度
'asdfg'.split('', 3) // ["a", "s", "d"]
// 以字符串s進行跟個
'asdfg'.split('s') // ["a", "dfg"]
// 以正則表達式匹配結果進行分割
'asdfg'.split(/s/) // ["a", "dfg"]
複製代碼

好比下面,一個簡易版的解析url中鍵值對參數

/*
 * 簡易解析url中鍵值對參數
 * @param url { String } 待解析的url
 * @return { key1: 1, key2: 2} 返回解析後的鍵值對的對象
 */
const parseQueryString = url => {
    if (!url) throw Error('缺乏待解析url')
    let result = {}
    const query = url.split('?')[1]
    query && query.split('&').forEach(e => {
        const parts = e.split('=');
        result[parts[0]] = parts[1];
    })
    return result;
}

parseQueryString('www.baidu.com?key1=1&key2=2') // {ke1: 1, key2: 2}複製代碼

那就再扯一下數組的join()方法吧,能夠理解爲字符串split()方法的副作用方法。該方法用於將數組轉換成字符串,接收一個參數,做爲拼接符,默認是英文逗號:

[1,2,3,4,5].join() // "1,2,3,4,5" // 默認逗號拼接
[1,2,3,4,5].join('a') // "1a2a3a4a5" // 自定義用字符a拼接複製代碼


相關文章
相關標籤/搜索