zepto源碼中的正則表達(dá)式

參考:https://segmentfault.com/a/1190000012515207?from=timeline
對于Zepto源碼分析,是每個前端修煉自己js技能的必經(jīng)之路。
在讀源碼過程中,最難以理解的地方,是里面出現(xiàn)的各種晦澀的正則表達(dá)式。本文主要分析對象是zepto@1.1.6源碼中的正則表達(dá)式。
這篇文章,主要總結(jié)了Zepto源碼中使用到的一些正則表達(dá)式,并分析每個正則的使用場景。
以《JavaScript正則表達(dá)式迷你書》為參考,可以完善正則表達(dá)式的學(xué)習(xí),并與本文形成照應(yīng)。
關(guān)鍵是一句話:正則表達(dá)式是匹配模式,要么匹配字符,要么匹配位置。

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

源碼位置:第10行
匹配目標(biāo)是否為html節(jié)點,比如:"<html>, <script>"這樣的單個未閉合節(jié)點,可視化形式為:

image.png

\s:貪婪匹配空白符;[^>]*表示:匹配到的"<"和">"中間內(nèi)容不能出現(xiàn)">";中間內(nèi)容出現(xiàn)兩個分支單詞字符或者!,里面()進(jìn)行捕獲分組,后面提取第一組的內(nèi)容。下面代碼中,則通過RegExp.$1提取。

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

源碼位置:第11行
驗證是否為單個閉合的html標(biāo)簽,形如:

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

可視化形式為:

image.png

(\w+) 分組引用,使用了捕獲分組的概念,Group #1(或者圖中的capture 1)為第一組數(shù)據(jù),所以作用在于后面使用\1提取前面對應(yīng)的數(shù)據(jù),后面還可以使用$1, $2捕獲每組匹配的內(nèi)容。
\s 表示空白符,包括:空格,水平制表符,垂直制表符,換行符,回車符,換頁符。
* 表示任意次數(shù)出現(xiàn)。
/? 則表示/出現(xiàn)或者不出現(xiàn)。
(?:</\1>|) 對應(yīng)的是非捕獲括號,指向要括號最原始的功能,但不會引用它。里面的\1,是第一個分組(Group #1)的內(nèi)容,主要是為了驗證這個標(biāo)簽是成對的,前后內(nèi)容一致。后面|則表示如果沒有匹配到成對的內(nèi)容,也可以什么內(nèi)容都沒有。比如匹配<hr />這類標(biāo)簽。

//  測試代碼段
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)); 
  //  這里捕獲一個完整的閉合標(biāo)簽,并生成對應(yīng)節(jié)點
};
3. tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig

源碼位置:第12行
匹配自閉合標(biāo)簽,形如:<div />
zepto里面主要作用:<div /> ==> <div></div>
可視化形式:

image.png

最后面的,/ig:兩個修飾符,g:表示全局匹配,i:表示忽略大小寫。
然后在看正則主體部分內(nèi)容,"<"和"/>"中間的內(nèi)容大致可以分為兩部分:

  • (?!area|br|col|embed|hr|img|input|link|meta|param)
    上面大致可以化簡成:(?!p),也就是要匹配位置。
    要解釋這部分,首先要對應(yīng)的提出(?=p),其中p是一個子模式,指代p前面的位置。也說明該位置后面的字符要匹配p。列舉書中實例:
var result = "hello".replace(/(?=l)/g, '#');
console.log(result);
// => "he#l#lo"

相應(yīng)的開頭提到的(?!p)就是反面意思

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

(?=p)(?!p)學(xué)名分別是:positive lookaheadnegative lookahead.
中文翻譯分別是:正向先行斷言負(fù)向先行斷言
這里我們可以理解為:#后面的字符不能匹配l,這里所說的#,在原字符串"hello"中是不存在的,只是代表字符之間的各個位置,輸出#h#ell#o#只是實例化匹配展示出來了對應(yīng)的位置。
<右邊不能是area, br, col, embed, hr, img, input, link, meta, param,比如像:<img />,<br />這樣就不需要轉(zhuǎn)化了。

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提取匹配到的數(shù)據(jù)。
([\w:]+)中+就是{1, }的簡寫,表示\w(數(shù)字、字母、下劃線)或者:至少出現(xiàn)一次,通常是標(biāo)簽名,如:div, span等等
(([\w:]+)[^>]
)多了[^>]表示匹配>以外的任意內(nèi)容,比如:<div class="div-class">中的class="div-class"。可以這么理解,比.能夠匹配所有內(nèi)容多加了一個條件

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行
通過檢測節(jié)點的nodeName屬性,判斷是否為body或者h(yuǎn)tml根節(jié)點
可視化形式:

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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 概述 正則表達(dá)式(英語:Regular Expression); 本質(zhì):用來記錄文本規(guī)則的代碼(為字符串定義規(guī)則,...
    magic_pill閱讀 264評論 0 2
  • 前言 對于正則,著稱火星文字,見名知意主要它晦澀難懂,一直以來,看到它總是怕怕的,在平時,也只是簡單的用用,其主要...
    itclanCoder閱讀 794評論 0 2
  • 正則表達(dá)式的元字符是包含特殊含義的字符,它們有一些特殊的功能,可以控制匹配模式的方式,反斜杠后的元字符失去其特殊含...
    Miss____Du閱讀 1,604評論 0 6
  • 2016-05-16 華杉 縱橫捭闔,聳動天下的公孫衍、張儀之流,不過是揣摩國君意圖,煽風(fēng)點火,狐假虎威,借刀殺人...
    郁萍閱讀 327評論 0 0
  • 你還在找實習(xí)嗎? 本人大三狗一枚,工科出生,一直在找和本專業(yè)相關(guān)的崗位,但是我已經(jīng)面試了兩家公司,都要群面,都是群...
    吃糖的米老鼠閱讀 362評論 1 1