JavaScript正则表达式中g标志详解_第1页
JavaScript正则表达式中g标志详解_第2页
JavaScript正则表达式中g标志详解_第3页
JavaScript正则表达式中g标志详解_第4页
JavaScript正则表达式中g标志详解_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第JavaScript正则表达式中g标志详解目录缘起解密过程搜索引擎源码层面结论

缘起

有一天在思否社区看到有个问题,大致描述如下

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

constreg=/[a-z]/g;

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

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

//如果正则不使用`g`标志可以得到所有的字母

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

对问题而言,遍历中的i就是一个字符,不需要用到g。

但是就我对正则的理解(过于浅薄)感觉上有没有g(只是全局搜索,不会匹配到就停下来)应该不影响,激发了我的好奇心。

上面题的建议写法如下

constreg=/[a-z]/g;

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

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

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

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

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

解密过程

首先可以确定的表现一定是g导致的

搜索引擎

打开MDN仔细查看g标志的作用,得到结论和我的理解无二。

我猜想应该就是g可能启用了某种缓存,又因为reg相对过滤器是全局变量,我将代码改为:

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

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

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

将正则声明到每一次遍历,得到结论就是正确的,验证了我的猜想。也得到了,缓存就是正则中的某个地方

下面我找到对应的源码来查看问题的原因

源码层面

由于最近在看Rust,所以使用Rust编写的源码查看

打开项目后,点击.进入vscode模式,command+p搜索regexp关键词

进入test.rs文件,command+f搜索/g可以找到在90行有个last_index()的测试

#[test]

fnlast_index(){

letmutcontext=Context::default();

letinit=r#"

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

//forward的作用:更改context,并返回结果的字符串。

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");

}

看到了有lastIndex关键字,这里再已经大致猜到问题的原因了,g标志存在匹配后的最后一个下标,导致出现问题。

我们将视线移入到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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论