欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一次JavaScript正則的詭異經(jīng)歷記錄

 更新時(shí)間:2022年04月21日 09:27:26   作者:Lam  
正則表達(dá)式是用于匹配字符串中字符組合的模式,下面這篇文章主要給大家介紹了一次JavaScript正則的詭異經(jīng)歷記錄,文中通過(guò)實(shí)例介紹的非常詳細(xì),需要的朋友可以參考下

事情是這樣的,最近在寫(xiě)一個(gè)Node功能的時(shí)候,遇到了一個(gè)正則的問(wèn)題,覺(jué)得挺有意思的,就記錄一下經(jīng)歷和最終問(wèn)題原因,希望也能幫助到同樣遇到的同學(xué)。

背景

我有一個(gè)Node服務(wù),希望對(duì)訪問(wèn)進(jìn)來(lái)的請(qǐng)求進(jìn)行標(biāo)記,如果請(qǐng)求進(jìn)來(lái)的path是我定義的路由,那么將標(biāo)記一個(gè)REQ,否則標(biāo)記一個(gè)IVL,用于對(duì)于整個(gè)服務(wù)的日志記錄進(jìn)行輸出。那么我通過(guò)服務(wù)啟動(dòng)時(shí),根據(jù)定義的路由,生成一個(gè)RouterMap,通過(guò)訪問(wèn)進(jìn)入時(shí),判斷path是否命中RouterMap來(lái)判斷是否預(yù)期訪問(wèn)。

大概的代碼如下:

export function getSourceMak(
? routerMap: AppRouterMap[],
? req: http.IncomingMessage,
): SourceMark.REQ | SourceMark.IVL | SourceMark.TST {
? const { url, method, headers } = req;
? const pathname = url.split('?')[0];
? const userAgent = headers['user-agent'];
? // 安全掃描
? if (userAgent?.includes('TST(Tencent') && userAgent.includes('Team)')) {
? ? return SourceMark.TST;
? }
? for (const item of routerMap) {
? ? const { reg } = item;
? ? if (reg.test(pathname) && item.method === method.toLocaleLowerCase()) {
? ? ? return SourceMark.REQ;
? ? }
? }
? return SourceMark.IVL;
}?

因?yàn)樯婕暗揭恍﹦?dòng)態(tài)路由的原因,不能直接通過(guò)path進(jìn)行相等判斷,需要對(duì)相應(yīng)的路由規(guī)則生成一個(gè)對(duì)應(yīng)的正則表達(dá)式,并且在服務(wù)啟動(dòng)時(shí)生成,保存在內(nèi)存中進(jìn)行復(fù)用。

生成正常代碼如下:

export function createRouterRegexp(url) {
  const urlBlock = url.split('/');
  const regBlock = urlBlock.map((block) => {
    if (block[0] === ':') {
      return '((?!/).)*';
    }
    return block;
  });
  return new RegExp(`^${regBlock.join('/')}$`, 'ig');
}

問(wèn)題

然后在進(jìn)行調(diào)試的時(shí)候發(fā)現(xiàn)一個(gè)奇怪的現(xiàn)象,假設(shè)我有一個(gè)路由為GET /cats/find的路由,通過(guò)打點(diǎn)發(fā)現(xiàn)對(duì)應(yīng)的正則表達(dá)式,/^\/cats\/find$/gi對(duì)/cats/find進(jìn)行匹配的時(shí)候,第一次為true,第二次為false,第三次為true,第四次為false,以此類推。

經(jīng)過(guò)反復(fù)驗(yàn)證,node代碼并沒(méi)有存在問(wèn)題,正則表達(dá)式也沒(méi)有問(wèn)題,那么我在瀏覽器中嘗試復(fù)現(xiàn)一下,也是得出同樣的問(wèn)題。至此我很確定,一定是有一些正則相關(guān)的坑是我以前沒(méi)有注意到。于是我反查了一下JavaScript的文檔,終于被我找到原因。

原因

通過(guò)查找MDN正則相關(guān)的文檔,被查到以下說(shuō)明

"nolink">當(dāng)設(shè)置全局標(biāo)志的正則使用test()

如果正則表達(dá)式設(shè)置了全局標(biāo)志,test() 的執(zhí)行會(huì)改變正則表達(dá)式 lastIndex屬性。連續(xù)的執(zhí)行test()方法,后續(xù)的執(zhí)行將會(huì)從 lastIndex 處開(kāi)始匹配字符串,(exec() 同樣改變正則本身的 lastIndex屬性值).

下面的實(shí)例表現(xiàn)了這種行為:

var regex = /foo/g; 
// regex.lastIndex is at 0 
regex.test('foo'); // true 
// regex.lastIndex is now at 3 
regex.test('foo'); // false

RegExp.prototype.test() - JavaScript | MDN

這不就是我遇到的問(wèn)題嗎?

通過(guò)文檔說(shuō)明得知,當(dāng)我們正則表達(dá)式帶有g(shù)標(biāo)識(shí)進(jìn)行全局匹配時(shí),匹配成功后,regex實(shí)例中會(huì)有一個(gè)lastIndex屬性去記錄本次命中正則的最后一位的下標(biāo)+1,用于在下一次調(diào)用test的時(shí)候,從lastIndex開(kāi)始進(jìn)行匹配。 以前我沒(méi)有遇到過(guò)大概率是因?yàn)橐韵略颍?/p>

每次進(jìn)行正則校驗(yàn)時(shí),都重新生成正則實(shí)例:/^\/cats\/find$/gi.test('/cats/find') 。

但是因?yàn)檫@次我將正則實(shí)例保存,并反復(fù)使用。從而導(dǎo)致問(wèn)題。

并且通過(guò)驗(yàn)證得出,當(dāng)匹配成功后,lastIndex會(huì)記錄下一次開(kāi)始的位置,但是當(dāng)匹配失敗,lastIndex會(huì)歸零從頭開(kāi)始。

至此這一次被坑經(jīng)歷耗時(shí)60分鐘左右,耽誤了吃飯最佳時(shí)間,導(dǎo)致飯?zhí)貌硕伎鞗](méi)有。但是同時(shí)也收獲到JavaScript在正則上一個(gè)容易被忽略的坑。好像也不虧。

總結(jié)

到此這篇關(guān)于一次JavaScript正則的詭異經(jīng)歷記錄的文章就介紹到這了,更多相關(guān)JavaScript正則經(jīng)歷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 原生JS實(shí)現(xiàn)圖片輪播 JS實(shí)現(xiàn)小廣告插件

    原生JS實(shí)現(xiàn)圖片輪播 JS實(shí)現(xiàn)小廣告插件

    這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)圖片輪播、小廣告插件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Javascript 使用function定義構(gòu)造函數(shù)

    Javascript 使用function定義構(gòu)造函數(shù)

    Javascript并不像Java、C#等語(yǔ)言那樣支持真正的類。但是在js中可以定義偽類。做到這一點(diǎn)的工具就是構(gòu)造函數(shù)和原型對(duì)象。首先介紹js中的構(gòu)造函數(shù)。
    2010-02-02
  • Javascript類定義語(yǔ)法,私有成員、受保護(hù)成員、靜態(tài)成員等介紹

    Javascript類定義語(yǔ)法,私有成員、受保護(hù)成員、靜態(tài)成員等介紹

    JS只是一門(mén)支持面向?qū)ο缶幊痰恼Z(yǔ)言,通過(guò)OO可以讓我們的代碼組織更加人性化??墒桥c傳統(tǒng)基與類的面向?qū)幊陶Z(yǔ)言不同它沒(méi)有類概念并且沒(méi)成員訪問(wèn)修飾符。這多少會(huì)給我們編程工作會(huì)帶來(lái)一些束縛
    2011-12-12
  • 實(shí)例詳解JavaScript中setTimeout函數(shù)的執(zhí)行順序

    實(shí)例詳解JavaScript中setTimeout函數(shù)的執(zhí)行順序

    關(guān)于javascript的運(yùn)行機(jī)制大家都應(yīng)該有所了解了吧,其實(shí)javascript是一個(gè)單線程的機(jī)制,但是因?yàn)殛?duì)列的關(guān)系它的表現(xiàn)會(huì)讓我們感覺(jué)是一個(gè)多線程的錯(cuò)覺(jué)。下面這篇文章通過(guò)實(shí)例主要給大家介紹了關(guān)于JavaScript中setTimeout函數(shù)執(zhí)行順序的相關(guān)資料,需要的朋友可以參考下。
    2017-07-07
  • javascript trie前綴樹(shù)的示例

    javascript trie前綴樹(shù)的示例

    這篇文章主要介紹了javascript trie單詞查找樹(shù)的示例,詳細(xì)的介紹了trie的概念和實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 數(shù)據(jù)排序誰(shuí)最快(javascript中的Array.prototype.sort PK 快速排序)

    數(shù)據(jù)排序誰(shuí)最快(javascript中的Array.prototype.sort PK 快速排序)

    今天在51js論壇中看到一個(gè)網(wǎng)友發(fā)布了一個(gè)javasctipt實(shí)現(xiàn)的快速排序的算法,前些日子工作中也涉及到j(luò)avasctipt中數(shù)據(jù)排序的應(yīng)用,當(dāng)時(shí)為了提高排序速度,使用的也是快速排序的算法。
    2007-01-01
  • layui實(shí)現(xiàn)checkbox的目錄樹(shù)tree的例子

    layui實(shí)現(xiàn)checkbox的目錄樹(shù)tree的例子

    今天小編就為大家分享一篇layui實(shí)現(xiàn)checkbox的目錄樹(shù)tree的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-09-09
  • 微信小程序組件通信和behavior使用詳解

    微信小程序組件通信和behavior使用詳解

    behaviors是小程序中,用于實(shí)現(xiàn)組件間代碼共享的特性,類似于 Vue.js 中的 “mixins”,這篇文章主要介紹了微信小程序組件通信和behavior使用,需要的朋友可以參考下
    2022-08-08
  • Sort()函數(shù)的多種用法

    Sort()函數(shù)的多種用法

    sort() 方法用于對(duì)數(shù)組的元素進(jìn)行排序。接下來(lái)通過(guò)本文給大家介紹Sort()函數(shù)的多種用法,對(duì)sort函數(shù)的用法相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)
    2016-03-03
  • js校驗(yàn)開(kāi)始時(shí)間和結(jié)束時(shí)間

    js校驗(yàn)開(kāi)始時(shí)間和結(jié)束時(shí)間

    這篇文章主要為大家詳細(xì)介紹了js校驗(yàn)開(kāi)始結(jié)束時(shí)間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05

最新評(píng)論