亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

一道小小的題目引發(fā)對javascript支持正則表達式相關(guān)方法的探討

Scholer / 893人閱讀

摘要:返回值返回值根據(jù)傳入的參數(shù)類型和規(guī)則的不同,返回的內(nèi)容不同,但總體來說,它是返回一個對象,而不是索引,如果沒匹配到任何符合條件的字符串,則返回。

本文發(fā)布在我的博客一道小小的題目引發(fā)對javascript支持正則表達式相關(guān)方法的探討
許可協(xié)議: 署名-非商業(yè)性使用-禁止演繹 4.0 國際 轉(zhuǎn)載請保留原文鏈接及作者。

以前對于正則是非常懼怕的,因為看不懂和學(xué)不會。但最近項目中頻繁的使用到了正則,因此強迫自己去學(xué)習(xí)了解,慢慢的體會到了他的魅力與強大。當(dāng)然學(xué)習(xí)正則初入門的時候有些枯燥難懂,但越學(xué)越覺得輕松。本文不準(zhǔn)備說關(guān)于正則本身的事兒,而是說一說關(guān)于javascript中關(guān)于正則的幾個方法中被很多人忽略的地方。

工具

說到正則,很多人都是從抄到改到自己寫,這個過程可能有時候很漫長。如一些工具能幫助你快速分析和學(xué)習(xí)正則,那么學(xué)習(xí)的過程你肯定要輕松得多。下面我推薦兩個我經(jīng)常使用的正則在線可視化工具,正則可視化工具圖解符合鐵路圖規(guī)律(其實不明白什么是鐵路一樣很容易看懂,只是一些細微的地方和我們的常規(guī)思維有點差別)。

regexper 我最常用的一個,個人覺得UI做得比其他好

regulex 備選,他有一個很舒心的功能,可以提供一段js,嵌套到你的網(wǎng)站,生成正則可視化圖

一道小小的題目

這道題目是在群里日常閑聊時,公司同事拋出來的,具體是出自哪里本人沒去考察。先先說說題目:

寫一個方法把一個數(shù)字末尾的連續(xù)0變成9,如1230000變成1239999

一道很簡單的題目,直接正則就能搞定,也許你會寫:

function zoreToNine(num){
    return (num + "").replace(/0/g,9);
}
//或者
function zoreToNine(num){
    return (num + "").replace(/[1-9]0+$/,9);
}

這也是此題的陷阱所在,按照上面的方法,1023000就會被轉(zhuǎn)化成1923999,這樣是不符合要求的,所以改進一下:

function zoreToNine(num){
    return (num + "").replace(/[1-9]0+$/,function($1){
        return $1.replace(/0/g,9);
    });
}
zoreToNine(1223000); //1223999
zoreToNine(1023000); //1023999

關(guān)于這個問題的解決方案@微醺歲月同學(xué)提供了一種,位置匹配的方法,簡單了很多,厲害!

"12300100000".replace(/0(?=(0+$)|)/g,9); //12300199999

當(dāng)然解決問題的方法很多,不一定非要用正則,還完全可以使用純算術(shù)的方法實現(xiàn),大家有興趣可以嘗試,閑話少說進入這次的主題:javascript支持正則表達式相關(guān)方法,注意并不是正則對象的方法。
上述方法使用了正則,有趣的是在回調(diào)函數(shù)里有一個$1,這個$1到底是什么?所有的匹配規(guī)則匹配后都有$1這個變量么?...一連串的問題,以前我從來沒有去追探過,趁著昨個比較空閑,去追探了一番,并在今天整理了一下,寫下此文記錄。

主角

javascript中正則對象有三個方法:test、execcompile,但是此次的主角并不是它們!我們討論的是能夠使用正則表示的相關(guān)方法:searchmatch、replacesplit,注意它們都是String對象的方法,使用它們必須要是String類型.

replace(rule[regexp/substr], replacement)

replace是一個用于替換字符串的方法,雖然看似簡單,但是它隱藏的機關(guān)也是常常被人忽略。具體分析一下它的特點:

它接收兩個參數(shù)
無副作用不影響原始變量
返回被改變的字符串(一定是字符串類型)

定義一些變量,方便全文取用。

let a = "12309800", b = "12309800[object Object]", b = "12309800{}";
參數(shù)rule

在一般情況,rule參數(shù)一般是正則、字符串、數(shù)字。
如果是字符串,將會在匹配到第一個符合條件的目標(biāo),結(jié)束方法;
如果是正則,則按照正則的規(guī)則進行匹配

//匹配第一個0替換成5
a.replace(0,5); //"12359800"
//匹配所有的0替換成5
a.replace(/0/g,5); //"12359855"
參數(shù)replacement

在一般情況,replacement參數(shù)是字符串、數(shù)字、者回調(diào)。

包含$的字符串

當(dāng)參數(shù)rule為正則,并且正則至少包含有一對完整的()時,如果replacement包含有$的字符串,那么對于$n(n為大于0的整數(shù),n的長度取決于正則中括號的對數(shù)),會被解析成一個變量。但是也僅僅只是作為一個變量,無法在字符串中進行計算,此時更類似特別的字符串模板變量。

一般情況下,$n中n的長度取決于正則中括號的對數(shù),$1表示第1對括號匹配的結(jié)果,$2表示第2對匹配的結(jié)果...在正則所有的括號對中,左括號出現(xiàn)在第幾個位置(或者說從左往右),則它就是第幾對括號,以此類推。姑且我們把這種規(guī)則成為正則匹配分割規(guī)則(ps:這完全是我自己取的一個名字,方便文章后面使用和記憶)。

a.replace(0,"$0"); //"123$09800"
a.replace(/00/g,"$0"); //"123098$0"
a.replace(/[1-9]0+$/,"$1"); //"12309$1"
a.replace(/([1-9](0+$))/,"$1"); //"12309800",此時$1為[1-9](0+$)匹配到的內(nèi)容,$2為0+$匹配到的內(nèi)容
a.replace(/([1-9])(0+$)/,"$1"); //"123098",此時$1為[1-9]匹配到的內(nèi)容,$2為0+$匹配到的內(nèi)容
a.replace(/([1-9])(0+$)/,"$1*$2"); //"123098*00",此處的$1和$2不會安照期待的情況進行乘法計算,要進行計算可以用回調(diào)

請注意:雖然目前參數(shù)replacement中攜帶有$n仍然能正常使用,但是這種方式已經(jīng)不被規(guī)范所推薦,更應(yīng)該使用回調(diào)來完成這個操作。這一點謝謝@lucky4同學(xué)的指出

如果正則中包含有全局匹配標(biāo)志(g),那么每次匹配的都符合上述規(guī)則

回調(diào)函數(shù)

先看例子:

a.replace(/[1-9]0+$/,function(){
    console.log(arguments); //["800",5,"12309800"]、
});
a.replace(/([1-9])0+$/,function(){
    console.log(arguments); //["800","8",5,"12309800"]
});
a.replace(/([1-9])(0+$)/,function(){
    console.log(arguments); //["800","8","00",5,"12309800"]
});
a.replace(/(([1-9])(0+$))/,function(){
    console.log(arguments); //["800","800","8","00",5,"12309800"]
});

回調(diào)函數(shù)的arguments數(shù)組部分組成:[完整匹配的字符串,$1,$2,...,$n,匹配的開始位置,原始字符串],$1...$n表示每個括號對的匹配,規(guī)則和前面的相同。
所以有一下規(guī)律:

let arr = [...arguments], len = arr.length;
(len >= 3) === true;
arr[0] = 完整匹配的字符串;
arr[len-2] = 匹配的開始位置;
arr[len-1] = 原始字符串;

注意:除了匹配的開始位置是Number類型外,其余的都是String類型

非常規(guī)類型參數(shù)

如果參數(shù)類型不是上述兩種情況,會發(fā)生什么呢?看看下面的例子:

a.replace(0,null); //123null9800
a.replace(0,undefined); //123null9800
a.replace(0,[]); //1239800
a.replace(0,Array); //1230,3,123098009800
b.replace({},5); //123098005
c.replace({},5); //"12309800{}"
a.replace(0,{}); //123[object Object]9800
a.replace(0,Object); //12309800

由上面的例子可以看出,如果非正則也非字符串,則有以下規(guī)則:

`null`變量,則會轉(zhuǎn)換成`"null"`字符串;
`undefined`變量,則會轉(zhuǎn)換成`"undefined"`字符串;
`[]`變量,則會調(diào)用`join()`方法轉(zhuǎn)換成字符串,默認以`,`分割,值得注意的是空數(shù)組將會被轉(zhuǎn)換成空字符串(沒有任何字符),通常會被匹配源字符串的開始位置(默認開始位置為空字符串);
"Array"變量,則會先轉(zhuǎn)成成一個匹配的數(shù)組,形如`[完整匹配的字符串,$1,$2,...,$n,匹配的開始位置,原始字符串]`,然后對它調(diào)用`join()`方法轉(zhuǎn)換成字符串,默認以`,`分割;
`{}`變量,則會調(diào)用`Object.protype.toString.call()`方法把`{}`轉(zhuǎn)換成`[object Object]`;
`Object`變量,則貌似什么都沒做

雖然可以傳入這些非正常參數(shù),但大多數(shù)情況下這些類型的參數(shù)對實際是毫無意義的,所以不建議傳入以上類型的參數(shù)。同上面的正則匹配分割規(guī)則一樣,為了方便使用稱呼,姑且我把上面的轉(zhuǎn)換規(guī)則稱為正則匹配參數(shù)轉(zhuǎn)換規(guī)則

match(rule[regex/substr])

match方法可在字符串內(nèi)檢索指定的值,或找到一個或多個正則表達式的匹配。
該方法類似indexOflastIndexOf,但是它返回指定的值,而不是字符串的位置;

參數(shù)

參數(shù)的傳遞除了常規(guī)的正則和字符串以外,其余所有類型的參數(shù)都會按照上述的正則匹配參數(shù)轉(zhuǎn)換規(guī)則轉(zhuǎn)換成字符串形式來匹配。

返回值

返回值根據(jù)傳入的參數(shù)類型和規(guī)則的不同,返回的內(nèi)容不同,但總體來說,它是返回一個對象,而不是索引,如果沒匹配到任何符合條件的字符串,則返回null。

非全局匹配正則

如果匹配規(guī)則是一個非全局匹配規(guī)則,那么,它此時的返回值是一個偽數(shù)組對象(likeArr),形如:[一個展開的匹配到的字符串?dāng)?shù)組, 匹配到的字符串位置, 原始字符串],它有如下規(guī)律:

var likeArr = a.match(regex);
likeArr[0] = 匹配到的字符串;
likeArr[1...n] = 正則匹配分割規(guī)則匹配的字符串;
likeArr.index = 匹配到字符串的位置
likeArr.inupt = 原始字符串

看例子:

a.match(/[1-9]0+$/); //[0:"800",index:5,input:"12309800"]
a.match(/([1-9])0+$/); //[0:"800",1:"8",index:5,input:"12309800"]
a.match(/[1-9](0+$)/); //[0:"800",1:"00",index:5,input:"12309800"]
a.match(/([1-9])(0+$)/); //[0:"800",1:"8",2:"00",index:5,input:"12309800"]
全局匹配正則

如果匹配規(guī)則是一個全局匹配規(guī)則(正在攜帶有g(shù)標(biāo)志),那么,它此時的返回值是一個數(shù)組對象(arr),形如:[匹配到的字符串?dāng)?shù)1,匹配到的字符串?dāng)?shù)2,匹配到的字符串?dāng)?shù)3];
看例子:

a.match(/[1-9]0/); //[0:"30",index:2,input:"12309800"]
a.match(/[1-9]0/g); //[0:"30",1:"80"]
search(rule[regex/substr])

search方法用于檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串。
stringObject中第一個與rule相匹配的子串的起始位置。如果沒有找到任何匹配的子串,則返回-1
注意:

search方法不執(zhí)行全局匹配,它將忽略標(biāo)志g。

忽略regexplastIndex屬性,總是從字符串的開始進行檢索,這意味著它總是返回stringObject的第一個匹配的位置

同樣,search可以傳入任何參數(shù)類型,它會遵循正則匹配參數(shù)轉(zhuǎn)換規(guī)則進行轉(zhuǎn)換

split(rule[regex/substr],len)

這個方法就不用多說,很常用的字符串分割方法。
第二個參數(shù)的作用就是限制返回值的長度,表示返回值的最大長度

當(dāng)然,它依然可以傳入任何參數(shù)類型,會遵循正則匹配參數(shù)轉(zhuǎn)換規(guī)則進行轉(zhuǎn)換

有一段加密的后的密碼,我們需要分離出字符串"12a344gg333tt445656ffa6778ii99"中的前三組數(shù)字,通過某種計算才能得出正確的密碼

"12a344gg333tt445656ffa6778ii99".split(/[a-zA-Z]+/g,3);//["12","334","333"]
最后

寫了這么多,突然發(fā)現(xiàn)以前僅僅是在用這些方法,了解得很不夠深入。越是學(xué)習(xí)才發(fā)現(xiàn)其中的奧秘!學(xué)無止境,與諸君共勉!
以上內(nèi)容如有錯誤之處,希望諸君不吝指出!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/89973.html

相關(guān)文章

  • 一道JavaScript題目學(xué)點正則

    摘要:起因是看到一道題目的另外一種解法特別有意思,同時也做一點正則的筆記,好理解。 這是一篇普通的教程,同時也是我的一篇筆記。起因是看到一道題目的另外一種解法特別有意思,同時也做一點正則的筆記,好理解。 題目 我印象中的這道題目是:有一組數(shù)組為[1,1,2,3,3,3,3,4,5,5,5,6,6]使用js把它變成[[1,1],2,[3,3,3],4,[5,5,5].[6,6]] 解法有很多,...

    rollback 評論0 收藏0
  • 前端優(yōu)化 - 收藏集 - 掘金

    摘要:雖然有著各種各樣的不同,但是相同的是,他們前端優(yōu)化不完全指南前端掘金篇幅可能有點長,我想先聊一聊閱讀的方式,我希望你閱讀的時候,能夠把我當(dāng)作你的競爭對手,你的夢想是超越我。 如何提升頁面渲染效率 - 前端 - 掘金Web頁面的性能 我們每天都會瀏覽很多的Web頁面,使用很多基于Web的應(yīng)用。這些站點看起來既不一樣,用途也都各有不同,有在線視頻,Social Media,新聞,郵件客戶端...

    VincentFF 評論0 收藏0
  • 一道面試題談?wù)労瘮?shù)柯里化(Currying)

    摘要:忍者秘籍一書中,對于柯里化的定義如下在一個函數(shù)中首先填充幾個參數(shù)然后再返回一個新函數(shù)的技術(shù)稱為柯里化。回到我們的題目本身,其實根據(jù)測試用例我們可以發(fā)現(xiàn),函數(shù)的要求就是接受單一函數(shù),例如但是與柯里化不同之處在于,柯里化返回的一個新函數(shù)。   歡迎大家再一次來到我的文章專欄:從面試題中我們能學(xué)到什么,各位同行小伙伴是否已經(jīng)開始了悠閑的春節(jié)假期呢?在這里提前祝大家雞年大吉吧~哈哈,之前有人說...

    cppprimer 評論0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗?dǎo)范式。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導(dǎo)范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評論0 收藏0
  • 深入理解js

    摘要:詳解十大常用設(shè)計模式力薦深度好文深入理解大設(shè)計模式收集各種疑難雜癥的問題集錦關(guān)于,工作和學(xué)習(xí)過程中遇到過許多問題,也解答過許多別人的問題。介紹了的內(nèi)存管理。 延遲加載 (Lazyload) 三種實現(xiàn)方式 延遲加載也稱為惰性加載,即在長網(wǎng)頁中延遲加載圖像。用戶滾動到它們之前,視口外的圖像不會加載。本文詳細介紹了三種延遲加載的實現(xiàn)方式。 詳解 Javascript十大常用設(shè)計模式 力薦~ ...

    caikeal 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<