




版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 跨境電商售賣合同協(xié)議
- 運(yùn)輸合同補(bǔ)充協(xié)議模板
- 轉(zhuǎn)讓機(jī)器技術(shù)合同協(xié)議
- 水桶購買協(xié)議書
- 期貨減產(chǎn)協(xié)議書
- 《血液輸注原理與應(yīng)用》課件
- 三方出資合伙合同
- 遮光補(bǔ)償協(xié)議書合同協(xié)議
- 通風(fēng)空調(diào)工程合同協(xié)議
- 諒解協(xié)議書格式模板
- 水利水電工程技術(shù)術(shù)語全
- 2024-2025教科版科學(xué)一年級(jí)下冊第二單元測試卷及答案
- 中國共產(chǎn)主義青年團(tuán)紀(jì)律處分條例試行解讀學(xué)習(xí)
- 醫(yī)療器械研究報(bào)告醫(yī)療器械產(chǎn)業(yè)現(xiàn)狀及未來發(fā)展趨勢分析報(bào)告(2025年)
- 數(shù)字孿生技術(shù)在智慧能源系統(tǒng)中的挑戰(zhàn)與機(jī)遇
- 拋石專項(xiàng)施工方案
- 電力增材再造技術(shù)的創(chuàng)新與發(fā)展
- 話劇導(dǎo)演合同協(xié)議
- 客服代理合同協(xié)議
- 躁狂癥病人的護(hù)理
- 高中女生預(yù)防性侵教育
評(píng)論
0/150
提交評(píng)論