zepto源码中的正则表达式

参考:https://segmentfault.com/a/1190000012515207?from=timeline
对于Zepto源码分析,是每个前端修炼自己js技能的必经之路。
在读源码过程中,最难以理解的地方,是里面出现的各种晦涩的正则表达式。本文主要分析对象是zepto@1.1.6源码中的正则表达式。
这篇文章,主要总结了Zepto源码中使用到的一些正则表达式,并分析每个正则的使用场景。
以《JavaScript正则表达式迷你书》为参考,可以完善正则表达式的学习,并与本文形成照应。
关键是一句话:正则表达式是匹配模式,要么匹配字符,要么匹配位置。

1. fragmentRE = /^s<(w+|!)[^>]>/

源码位置:第10行
匹配目标是否为html节点,比如:"<html>, <script>"这样的单个未闭合节点,可视化形式为:

image.png

\s:贪婪匹配空白符;[^>]*表示:匹配到的"<"和">"中间内容不能出现">";中间内容出现两个分支单词字符或者!,里面()进行捕获分组,后面提取第一组的内容。下面代码中,则通过RegExp.$1提取。

fragmentRE.test("<sccc/>") && RegExp.$1;
//  "sccc"
2. singleTagRE = singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/

源码位置:第11行
验证是否为单个闭合的html标签,形如:

"<hr/>, <script></script>"

可视化形式为:

image.png

(\w+) 分组引用,使用了捕获分组的概念,Group #1(或者图中的capture 1)为第一组数据,所以作用在于后面使用\1提取前面对应的数据,后面还可以使用$1, $2捕获每组匹配的内容。
\s 表示空白符,包括:空格,水平制表符,垂直制表符,换行符,回车符,换页符。
* 表示任意次数出现。
/? 则表示/出现或者不出现。
(?:</\1>|) 对应的是非捕获括号,指向要括号最原始的功能,但不会引用它。里面的\1,是第一个分组(Group #1)的内容,主要是为了验证这个标签是成对的,前后内容一致。后面|则表示如果没有匹配到成对的内容,也可以什么内容都没有。比如匹配<hr />这类标签。

//  测试代码段
singleTagRE.test("<hr />") && RegExp.$1 //  "hr"

singleTagRE.test("<script></script>") && RegExp.$1  //  "script"

singleTagRE.test("<script></sscript>") && RegExp.$1 //  false

//  zepto总的源码
zepto.fragement = function(html, name, properties) {
  var dom, nodes, container;

  //  A special case optimization for a single tag
  if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1)); 
  //  这里捕获一个完整的闭合标签,并生成对应节点
};
3. tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig

源码位置:第12行
匹配自闭合标签,形如:<div />
zepto里面主要作用:<div /> ==> <div></div>
可视化形式:

image.png

最后面的,/ig:两个修饰符,g:表示全局匹配,i:表示忽略大小写。
然后在看正则主体部分内容,"<"和"/>"中间的内容大致可以分为两部分:

  • (?!area|br|col|embed|hr|img|input|link|meta|param)
    上面大致可以化简成:(?!p),也就是要匹配位置。
    要解释这部分,首先要对应的提出(?=p),其中p是一个子模式,指代p前面的位置。也说明该位置后面的字符要匹配p。列举书中实例:
var result = "hello".replace(/(?=l)/g, '#');
console.log(result);
// => "he#l#lo"

相应的开头提到的(?!p)就是反面意思

var result = "hello".replace(/(?!l)/g, '#');
console.log(result);
//  => "#h#ell#o#"

(?=p)(?!p)学名分别是:positive lookaheadnegative lookahead.
中文翻译分别是:正向先行断言负向先行断言
这里我们可以理解为:#后面的字符不能匹配l,这里所说的#,在原字符串"hello"中是不存在的,只是代表字符之间的各个位置,输出#h#ell#o#只是实例化匹配展示出来了对应的位置。
<右边不能是area, br, col, embed, hr, img, input, link, meta, param,比如像:<img />,<br />这样就不需要转化了。

var tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;
"<img />".replace(tagExpanderRE, "<$1></$2>");  //  输出 "<img />"
  • (([\w:]+)[^>]*)

这里使用了捕获分组,分了两组:(([\w:]+)[^>])和([\w:]+),作用在于,replace的时候可以通过$1和$2提取匹配到的数据。
([\w:]+)中+就是{1, }的简写,表示\w(数字、字母、下划线)或者:至少出现一次,通常是标签名,如:div, span等等
(([\w:]+)[^>]
)多了[^>]表示匹配>以外的任意内容,比如:<div class="div-class">中的class="div-class"。可以这么理解,比.能够匹配所有内容多加了一个条件

var tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;
'<div class="div-class" />'.replace(tagExpanderRE, "<$1></$2>");  //  输出"<div class="div-class"></div>"
4. rootNodeRE = /^(?:body|html)$/i

源码位置:第13行
通过检测节点的nodeName属性,判断是否为body或者html根节点
可视化形式:

image.png

var rootNodeRE = /^(?:body|html)$/i;
var htmlDom = document.querySelector("html");
rootNodeRE.test(htmlDom.nodeName);  //  输出 true
var divDom = document.querySelector("div");
rootNodeRE.test(divDom.nodeName); //  输出 false
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 概述 正则表达式(英语:Regular Expression); 本质:用来记录文本规则的代码(为字符串定义规则,...
    magic_pill阅读 255评论 0 2
  • 前言 对于正则,著称火星文字,见名知意主要它晦涩难懂,一直以来,看到它总是怕怕的,在平时,也只是简单的用用,其主要...
    itclanCoder阅读 757评论 0 2
  • 正则表达式的元字符是包含特殊含义的字符,它们有一些特殊的功能,可以控制匹配模式的方式,反斜杠后的元字符失去其特殊含...
    Miss____Du阅读 1,578评论 0 6
  • 2016-05-16 华杉 纵横捭阖,耸动天下的公孙衍、张仪之流,不过是揣摩国君意图,煽风点火,狐假虎威,借刀杀人...
    郁萍阅读 312评论 0 0
  • 你还在找实习吗? 本人大三狗一枚,工科出生,一直在找和本专业相关的岗位,但是我已经面试了两家公司,都要群面,都是群...
    吃糖的米老鼠阅读 343评论 1 1