jQuery源码分析之jQuery中常用正则表达式分析

请提前阅读:点击打开链接

正则表达式分析一:

var rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i;
//打印true,\s*是贪婪匹配,表示直接跳到空格的最后,也就是跳过所有的空格,接着去匹配后面的字符!如果后面没有匹配到,那么就回溯!
alert(rchecked.test("checked "));
//打印true,因为是贪婪匹配,那么\s*会直接跳过所有的空格去匹配后面的字符,如果没有匹配到就会回溯,所以这里的等号前后可以有任意多的空格!
alert(rchecked.test("checked=xcheckedx"));

//打印null,原因在于这里的捕获组前面用了?:表示不会保存捕获组的数据!,用于或选择符的时候较好,如上面的[^=]|=\s*.checked.
alert("checked=xchecked".match(rchecked));

note:弄清楚什么是贪婪模式!

正则表达式分析2:

//该正则表达式也是用?:不让存储捕获组的数据,同时这里还用到了jQuery前面必须有空格
//而且必须有引号的正则表达式,收获:空格+引号
var rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g;
alert(rinlinejQuery.test(' jQuery123="null"'));
正则表达式分析3:

//下面打印Windows,也就是exec返回的数组只有一个元素"Windows"
//?!表示获取不是以特定字符形式结尾的字符串前缀!
var reg=/Windows(?!95|98|NT|2000)/;
alert(reg.exec("Windows3.1"));

//如果<后面不是area,br,col等那么就获取前面的<字符,否则不获取前面的,也就是打印null!
var reg1=/<(?!area|br|col|embed|hr|img|input|link|meta|param)/;
alert(reg1.exec("<html>"));

//打印数组[<html/>,html,html],前面的那个括号不算捕获组,后面两个捕获组一样,但是如果传入的参数是<html id="n1"/>两个捕获组就不一样!
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
alert(rxhtmlTag.exec("<html/>"));

正则表达式分析4:

var rscriptType = /^$|\/(?:java|ecma)script/i;
//打印true,因为^$表示是空的
alert(rscriptType.test(""));
//打印true,同时是javascript或者ecmascript都是true
alert(rscriptType.test("/javascript"));
//打印true,这里是test方法,所以他会从字符串的第一个字符开始匹配正则表达式,然后不断往后移动一个字符!
alert(rscriptType.test(" /javascript"));
//打印false
alert(rscriptType.test(" "));

note:用于测试script标签的type属性,type属性可以是空或者含有"/javascript"或者"/ecmascript"就可以!

正则表达式分析5:

var rtagName = /<([\w:]+)/;
//打印false,也就是<后面至少要有一个字符a-zA-Z0-9_
alert(rtagName.test("<"));
//打印true
alert(rtagName.test("<html"));
//exec方法会保存匹配的结果和捕获组的值,所以打印[<html,html]
alert(rtagName.exec("<div"));
正则表达式分析6:

//匹配tbody,要记住正则表达式的匹配机制,从第一个字母开始进行匹配,每次往后推动一个字母
var rtbody = /<tbody/i;
alert(rtbody.test("   <tbody"));
正则表达式分析7:

var rscriptTypeMasked = /^true\/(.*)/;
//以true开头,接着是反斜杠,然后是一个任意字符,但是要记住test的检测规则!
alert(rscriptTypeMasked.test("true/x"));
//打印[true/x,x]数组,打印第一个匹配元素和捕获组
alert(rscriptTypeMasked.exec("true/x"));
正则表达式分析8:

var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video";
var rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i");
//打印true,[\\s/>]表示是空格或者反斜杠或者>字符,只要有一个这样的字符就匹配了!,但是要记住通过RegExp构造函数要
//进行双重转义,也就是里面的反斜杠都是成双的!
alert(rnoshimcache.test("<article  "));
//但是这里的?:表示不保存捕获组,也就是打印的数组length是1,打印[<article ]
alert(rnoshimcache.exec("<article "));

note:正则表达式?:表示不保存捕获组,同时在RegExp中要双重转义!

正则表达式分析9:

var reg=/Windows(?=95|98|NT|2000)/;
var rjsonp = /(=)\?(?=&|$)|\?\?/;
//打印[Windows]表示只有Windows后面的睡是95,98,NT,2000才获取前面的Windows
alert(reg.exec("Windows95"));
//打印null
alert(reg.exec("Windows5"));
//这个rjsonp用于jsonp请求的,第一个字符是等号,然后第二个字符是问号,因为\?是转义为?,然后接下来的字符是
//&或者$,或者是两个问号!
alert(rjsonp.test("=?&"));
//打印true,表示这里的或者符号是(?=&|$)与\?\?两者选择其一
alert(rjsonp.test("=???"));
//打印["=?","="]所以(?=&|$)不是捕获组!,只有前面的(=)是捕获组!这里的保存是"=?"不包括后面的&符号!
alert(rjsonp.exec("=?&"));
//注意:这里打印null,因为这里的$在正则表达式中表示末尾,如果要是$,那么就要转义!
alert(rjsonp.exec("=?$"));
//打印["=?","="],因为上面的$表示结束符!所以这里的问号就是结束了
alert(rjsonp.exec("=?"));

note:要学会正向肯定预查,而且预查不是捕获组,不会保存到结果数组中;学会转义字符的运用;这个正则表达式用于jsonp请求,表示要么带了参数=?&形式,要么是=?不带参数的形式!

正则表达式分析10:

var rhtml = /<|&#?\w+;/;
//这个正则表达式用于匹配HTML特殊字符,HTML要么以<开头要么以&开头
//&后面如果有#也是可以的,这种情况也是表示特殊字符,如&#934表示Φ
//或只是表示|符号前后的一个字符!
//打印[<]
alert(rhtml.exec("<"));
//打印[Φ]
alert(rhtml.exec("&#934;"));
note:要知道html标签是以<或者&开头的,同时在&后可以有#号,这时候也是表示特殊的字符,如Φ!打开阅读
正则表达式分析11:

var rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
//用于?:里面的或符号表示是或前面或者或后面的一个整体!
//但是依然不会保存捕获组的数据!
//打印[<!--]
alert(rcleanScript.exec("<!---->  "));
//打印["我是html中的注释"]
var str="<!--我是html中的注释--> ";
alert(str.replace(rcleanScript,""));
//打印[<![CDATA[,]]>]第一个元素为<![CDATA[,第二个元素为]]>
alert("<![CDATA[alert('xxx')]]>".match(rcleanScript));
//打印"]]>",从输出结果可以看出,两个括号中间的或符号是前面整体和后面整体的或,也就是\s*<!(?:\[CDATA\[|--)和(?:\]\]|--)>\s*$的或!
alert(rcleanScript.exec("<![CDATA[alert('xxx')]]>"));
//打印[alert("xxx")]
alert("<![CDATA[alert('xxx')]]>".replace(rcleanScript,""));
note:要学会有捕获组的时候的或是整个前面部分和整个后面的所有部分的或,这里前面是^\s*<!(?:\[CDATA\[|--)后面是(?:\]\]|--)>\s*$;在replace中正则是全局的情况下调用的match方法选择所有匹配的部分,然后用第二个参数进行替换;这个正则表达式用于去除 <!---->和<![[CDATA和]]>部分从而获取其中的js和注释部分等!

正则表达式分析12:

var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
//这个正则表达式用于获取html标签,可以匹配<div/>因为在匹配<div/>空标签的时候后面用的是或表达式,表示空的!
//可以用\n引用前面表达式匹配的内容,记住是匹配的内容而不是表达式!
alert(rsingleTag.exec("<div/>"));//打印[<div/>,div]
note:可以用\n引用恰面正则表达式的内容,n是前面的捕获组!记住这里是匹配的内容而不是前面的正则表达式!
正则表达式分析13:

var rmsPrefix = /^-ms-/,
//搜索-符号后面的第一个字符,该字符可能是数字也可能是a-z字母,而且是全局的搜索!
	rdashAlpha = /-([\da-z])/gi;
//打印["-ms-"]
alert(rmsPrefix.exec("-ms-transform"));
var fcamelCase = function( all, letter ) {
		return letter.toUpperCase();
	};
var string="-ms-transform";
//第一个正则表达式是取出属性前面的第一个中划线,第二个是把替换过后的文本全局搜索中划线(这里是全局,也就是调用match全局搜索)
//给函数fcamelCase传入的参数为:第一个是匹配的文本,这里是中划线,第二个以后是捕获组,接着是下标,接着是总的字符串,
//这里的all是"-t"也就是整个正则表达式的值,第二个letter就是捕获组的值,为"t"
alert(string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ));
note:首先把-ms-替换为-ms,然后调用replace方法传入函数,该函数的第一个形参表示整个正则表达式匹配的结果,第二个形参就是捕获组的结果,最后就是把-ms-transform改成msTransform,把-ms-transform-xx改成msTransformXx因为第二个replace是全局的!
正则表达式分析14:

var reg=/[^abc]/g;
//虽然这里是g模式,但是因为这里[^abc]只是表示一个字符,所以打印[p]也就是exec只是匹配第一个字符!
alert(reg.exec("plain"));
var reg=/[^.]/g;
//这里打印[x]表示这个元素不能是点,虽然点在正则表达式里面有特殊的含义,但是在用于非的时候不需要转义!(加转义和不加转义是一样的!)
alert(reg.exec(".xxx"));
var rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
//[^.]*表示不是点的多个字符
//打印[click.test.sex,click,"test.sex"]
alert(rtypenamespace.exec("click.test.sex"));
note:学会[^.]表示不是点的任意字符,里面加转义和不加转义的结果是一样的;这个正则表达式用于获取事件类型和事件发生的命名空间,如"test.sex"就是命名空间,而“click”就是事件类型!
正则表达式分析15:

<pre name="code" class="javascript">var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
//正则表达式的source属性保存的是原生的文本,不管通过RegExp构造函数还是通过正则表达式字面量都是一样的!
var rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" );
//打印[+=10,+,10]
alert(rrelNum.exec("+=10"));

 
note:在jQuery.style源码中出现,将相对数字字符串类型转为相对数字类型! result+=6表示result=result+6!正则表达式分析16: 

var rneedsContext=/^[\x20\t\r\n\f]*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\([\x20\t\r\n\f]*((?:-\d)?\d*)[\x20\t\r\n\f]*\)|)(?=[^-]|$)/i;
//\x20表示的是空格!空格Ascii是32,16进制表示\x20
//或表示整个前面的部分和后面整个部分的或!,所以alert(rneedsContext.test(">"))为true
			//返回true								
			alert(rneedsContext.test(":even"));
			//打印true
			alert(rneedsContext.test(":first"));
			//打印false
			alert(rneedsContext.test(".n7"));
			//打印true,因为这里是test,所以要知道正则表达式匹配是从第一个字母开始匹配的!
			alert(rneedsContext.test("p:eq(0)"));
			//打印true
			alert(rneedsContext.test("p:even)"));
note:这个正则表达式用于closest方法!要注意的还是或表示前面整个部分和后面整个部分的或!,如果要加上括号那么要对它进行转义!
正则表达式分析17:

var reg=/industr(?:y|ies)/;
var reg1=/^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$/i;
//打印[industries]
alert(reg.exec("industries"));
//打印true,?:只是表示不保存捕获组!
alert(reg1.test("checked"));
note:?:的作用只是为了让正则表达式更加简洁,同时不保存捕获组的信息!如上面的正则表达式也可以是/industries|industry但是不简洁!
正则表达式分析18:

var rnotwhite = (/\S+/g);
//打印[hello]
alert(rnotwhite.exec(" hello you are mine"));
//打印[hello,you,are,mine],\S匹配除了换行符,制表符,空格等不可见的所有字符!
alert(" hello you are mine".match(rnotwhite));
正则表达式分析19:

var risSimple = /^.[^:#\[\.,]*$/;
//表示任何字符开头的,但是第二个字符不是:,#,[,.,逗号的任何字符
//打他true
alert(risSimple.test(" 1"));
//打印false,因为第二个之后的字符不能是括号里面的字符!
alert(risSimple.test(" 1#"));
正则表达式分析20:

var rformElems = /^(?:input|select|textarea)$/i,
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,//可以是click,mouse,pointer,contextMenue任何一种
	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
var rcheckableType = (/^(?:checkbox|radio)$/i);
var rmargin = (/^margin/);
var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );//如果传入alert(rnumnonpx.test("20a%a%"));打印tue,在curCss源码中使用!用于将具有奇怪结尾的数字转为像素!
rdisplayswap = /^(none|table(?!-c[ea]).+)/,
	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
rposition = /^(top|right|bottom|left)$/;

我们把上面的一个正则表达式单独说一下:这篇博客对应于jQuery源码函数curCss的hack

//pnum除了\d以外前后的部分都可以不存在!
var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
alert(rnumnonpx.exec("1em"));
//可以是a-z的任何一个字符或者%,其中%用于表示如相对宽度,a-z用于表示如1em的font-size的值!
var reg1=/[a-z%]/;
alert(reg1.test("em"));

补充1:(用于buildFragment函数)

var s="javascript";
var b=s.replace(/(hello)(you)/,"$2-$1");
alert(b);//打印javascript
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
var str='<div>我在这里你在那里</div>';
var result=str.replace( rxhtmlTag, '<$1></$2>' )
alert(result);//打印"<div>我在这里你在那里</div>"
note:对于replace方法来说如果正则表达式不能有效匹配字符串那么对字符串没有任何影响!这个正则表达式的作用是把<div/>变化成为<div></div>

补充2:(有或符号的正则表达式)

var rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/;
alert(rquickExpr.exec("#div1").length);//长度为4
var reg=/^(?:#([\w-]+)|([\w]+)|(\w+))/;
alert(reg.exec("#div1").length);//长度也是4,虽然前面第一个或已经满足了,而且也保存了捕获组,但是因为后面是或,所以还是会每个匹配一遍!

补充3:(有或符号的正则表达式)

var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
//打印[#div1,,div1]
alert(rquickExpr.exec("#div1"));

note:很可能会认为会打印["#div1","div1"]但实际上打印["#div1",,"div1"]。其中不保存捕获组是"?:”外面的捕获组不保存,但是或的捕获组还是会保存的!也就是会保存里面两个表示捕获组的值!

补充4:(匹配成功就会返回,不会继续匹配或)

//打印数组[java,java,,]
var reg=/(java)|(script)|(Maile)/;
alert(reg.exec("javascriptMaile"));

补充5:

//打印数组[script,,script,]
var reg=/(java)|(script)|(Maile)/;
alert(reg.exec("scriptMaile"));
note:捕获组还是从前往后排列的,匹配到script时候满足条件放入结果数组,接着第一个捕获组是"",第二个是自己的捕获组为scipt,接着捕获组为""!

补充6:(最终目地:学会parseJSON的正则表达式)

var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;

两篇博客中学到了几个概念:

ComputedStyle:经过计算过后的值,如50%要计算为特定的像素值
CascadeStyle:就是如50%或者em等相对单位的像素值!
InlineStyle:就是通过element.style.propertyName设定的值!
注意:除了IE都可以用document.defaultView.getComputedStyle获取到computedStyle,但是只有IE可以获取到cascadeStyle,也就是用elem.currentStyle
获取,所有浏览器都尅获取inline style,包括IE4。
解决方法:通过cascadeValue和自己的祖先来计算computedValue,例如visibility,要计算他是很容易的,如果值是inherit那么一直向上查找祖先元素
直到找到那个祖先元素。
overrideType:在w3c DOM中指的是document.defaultView.getOverrideStyle,在IE中指的是element.runtimeStyle,它可以让你覆盖style中的属性,同时覆盖的时候的特点就是:(1)具有最高的特权 (2)当你用cssText或者innerHTML时候他不会从DOM中序列化出来。getOverrideStyle在gecko中不支持,所以只有在IE中有用!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值