JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解_第1頁
JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解_第2頁
JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解_第3頁
JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解_第4頁
JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第JavaScript正則表達(dá)式中g(shù)標(biāo)志詳解目錄緣起解密過程搜索引擎源碼層面結(jié)論

緣起

有一天在思否社區(qū)看到有個(gè)問題,大致描述如下

constlist=['a','b','-','c','d'];

constreg=/[a-z]/g;

constletters=list.filter(i=reg.test(i));

//letters===['a','c'];

//如果正則不使用`g`標(biāo)志可以得到所有的字母

//為什么加入`g`之后就不可以了

對(duì)問題而言,遍歷中的i就是一個(gè)字符,不需要用到g。

但是就我對(duì)正則的理解(過于淺?。└杏X上有沒有g(shù)(只是全局搜索,不會(huì)匹配到就停下來)應(yīng)該不影響,激發(fā)了我的好奇心。

上面題的建議寫法如下

constreg=/[a-z]/g;

reg.test('a');//=true

reg.test('a');//=false

reg.test('a');//=true

reg.test('a');//=false

reg.test('a');//=true

解密過程

首先可以確定的表現(xiàn)一定是g導(dǎo)致的

搜索引擎

打開MDN仔細(xì)查看g標(biāo)志的作用,得到結(jié)論和我的理解無二。

我猜想應(yīng)該就是g可能啟用了某種緩存,又因?yàn)閞eg相對(duì)過濾器是全局變量,我將代碼改為:

constlist=['a','b','-','c','d'];

constletters=list.filter(i=/[a-z]/g.test(i));

//letters===['a','b','c','d'];

將正則聲明到每一次遍歷,得到結(jié)論就是正確的,驗(yàn)證了我的猜想。也得到了,緩存就是正則中的某個(gè)地方

下面我找到對(duì)應(yīng)的源碼來查看問題的原因

源碼層面

由于最近在看Rust,所以使用Rust編寫的源碼查看

打開項(xiàng)目后,點(diǎn)擊.進(jìn)入vscode模式,command+p搜索regexp關(guān)鍵詞

進(jìn)入test.rs文件,command+f搜索/g可以找到在90行有個(gè)last_index()的測試

#[test]

fnlast_index(){

letmutcontext=Context::default();

letinit=r#"

varregex=/[0-9]+(\.[0-9]+)/g;

//forward的作用:更改context,并返回結(jié)果的字符串。

eprintln!("{}",forward(mutcontext,init));

assert_eq!(forward(mutcontext,"regex.lastIndex"),"0");

assert_eq!(forward(mutcontext,"regex.test('1.0foo')"),"true");

assert_eq!(forward(mutcontext,"regex.lastIndex"),"3");

assert_eq!(forward(mutcontext,"regex.test('1.0foo')"),"false");

assert_eq!(forward(mutcontext,"regex.lastIndex"),"0");

}

看到了有l(wèi)astIndex關(guān)鍵字,這里再已經(jīng)大致猜到問題的原因了,g標(biāo)志存在匹配后的最后一個(gè)下標(biāo),導(dǎo)致出現(xiàn)問題。

我們將視線移入到mod.rs文件中,搜索test

在631行看到了fntest()方法

pub(crate)fntest(

this:JsValue,

args:[JsValue],

context:mutContext,

)-JsResultJsValue{

//1.LetRbethethisvalue.

//2.IfType(R)isnotObject,throwaTypeErrorexception.

letthis=this.as_object().ok_or_else(||{

context

.construct_type_error("RegEtotype.testmethodcalledonincompatiblevalue")

});

//3.LetstringbeToString(S).

letarg_str=args

.get(0)

.cloned()

.unwrap_or_default()

.to_string(context);

//4.LetmatchbeRegExpExec(R,string).

letm=Self::abstract_exec(this,arg_str,context);

//5.Ifmatchisnotnull,returntrue;elsereturnfalse.

ifm.is_some(){

Ok(JsValue::new(true))

}else{

Ok(JsValue::new(false))

}

在test()方法中找到了Self::abstract_exec()方法

pub(crate)fnabstract_exec(

this:JsObject,

input:JsString,

context:mutContext,

)-JsResultOptionJsObject{

//1.Assert:Type(R)isObject.

//2.Assert:Type(S)isString.

//3.LetexecbeGet(R,"exec").

letexec=this.get("exec",context);

//4.IfIsCallable(exec)istrue,then

ifletSome(exec)=exec.as_callable(){

//a.LetresultbeCall(exec,R,?S?).

letresult=exec.call(this.clone().into(),[o()],context);

//b.IfType(result)isneitherObjectnorNull,throwaTypeErrorexception.

if!result.is_object()!result.is_null(){

returncontext.throw_type_error("regexpexecreturnedneitherobjectnornull");

//c.Returnresult.

returnOk(result.as_object().cloned());

//5.PerformRequireInternalSlot(R,[[RegExpMatcher]]).

if!this.is_regexp(){

returncontext.throw_type_error("RegExpExeccalledwithinvalidvalue");

//6.ReturnRegExpBuiltinExec(R,S).

Self::abstract_builtin_exec(this,input,context)

}

又在Self::abstract_exec()方法中找到了Self::abstract_builtin_exec()方法

pub(crate)fnabstract_builtin_exec(

this:JsObject,

input:JsString,

context:mutContext,

)-JsResultOptionJsObject{

//1.Assert:RisaninitializedRegExpinstance.

letrx={

letobj=this.borrow();

ifletSome(rx)=obj.as_regexp(){

rx.clone()

}else{

returncontext.throw_type_error("RegExpBuiltinExeccalledwithinvalidvalue");

//2.Assert:Type(S)isString.

//3.LetlengthbethenumberofcodeunitsinS.

letlength=input.encode_utf16().count();

//4.LetlastIndexbe?(ToLength(Get(R,"lastIndex"))).

letmutlast_index=this.get("lastIndex",context).to_length(context);

//5.LetflagsbeR.[[OriginalFlags]].

letflags=rx.original_flags;

//6.Ifflagscontains"g",letglobalbetrue;elseletglobalbefalse.

letglobal=flags.contains('g');

//7.Ifflagscontains"y",letstickybetrue;elseletstickybefalse.

letsticky=flags.contains('y');

//8.Ifglobalisfalseandstickyisfalse,setlastIndexto0.

if!global!sticky{

last_index=0;

//9.LetmatcherbeR.[[RegExpMatcher]].

letmatcher=rx.matcher;

//10.Ifflagscontains"u",letfullUnicodebetrue;elseletfullUnicodebefalse.

letunicode=flags.contains('u');

//11.LetmatchSucceededbefalse.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論