1、空白
-
// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
-
whitespace = "[\\x20\\t\\r\\n\\f]",
在字符串中,斜杠是用於轉義的,若想輸出斜杠,必須采用雙斜杠來表示。上述字符串若直接用正則表達式對象來表示,如下:
whitespace = /[\x20\t\r\n\f]/,
之所以將五種字符定義為空白,出此CSS3標准,詳見:http://www.w3.org/TR/css3-syntax/ 4.1章節的whitespace邏輯圖。其原話:Only the characters "space" (U+0020), "tab" (U+0009), "line feed" (U+000A), "carriage return" (U+000D), and "form feed" (U+000C) can occur in whitespace。
\\x20表示空格,\\t表示制表符,\\r表示回車符(即行結束符),\\n表示換行符,\\f表示換頁符
2、標識符
雖然這里的英文不是標識符,但是,其實際用於對TAG、CLASS等標識符的判斷,故此處把它翻譯成標識符。
-
// http://www.w3.org/TR/css3-syntax/#characters
-
characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",,
可以看出,標識符可以由三種類型組成,一:\\\\. ;二:[\\w-];三:[^\\x00-\\xa0]。其CSS 3標准詳見:http://www.w3.org/TR/css3-syntax/ 4.1章節的ident-token圖。當然,細心的人們會發現,此正則表達式並沒有完全按照標准來寫,不過,這已能處理常見的絕大多數情況了,足以,畢竟還要考慮效率問題嘛。
第一部分:\\\\.,代表轉義字符(包括unicode碼),由反斜杠(\)打頭后跟除換行和行結束符外的任意字符的字符串,在此,jQuery沒有按照標准來匹配轉義字符,而是用小數點來代表其后的字符,在實際代碼中,會在Attr、Class、Id等類型名稱和類型值轉換中進行精確匹配。其CSS 3標准詳見:http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
第二部分:[\\w-],表示由數字、英文字母以及中划線組成的標識符。
第三部分:[^\\x00-\\xa0],表示非ASCII碼。
3、標識
-
// Loosely modeled on CSS identifier characters
-
// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
-
// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
-
identifier = characterEncoding.replace( "w", "w#" ),
這里為何需要加個#,不得而知,即便查了它給出的標准文檔,也沒有找到原因,且標准中標識符並沒有允許使用#字符。哪位找到原因了,請分享一下。而且identifier事實上用於值得判斷而非標識符的判斷,就我自己僅會在href中使用#字符,故推測是否用於支持對href值的判斷,故加了這個#。
4、屬性選擇器
-
// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
-
attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
-
"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
屬性基本格式如下:
[ 屬性名稱 匹配符號 值 ]
舉例如下:
[ title != "hello" ]
上述屬性選擇器表示title屬性值不等於hello
正則表達式從左到右依次解釋如下:
"\\[" 表示左方括號
whitespace + "*" 表示前后兩者之間的任意多個空白字符,后同
"*(" + characterEncoding + ")" 表示屬性名稱
(?:([*^$|!~]?=) 表示=、*=、^=、$=、|=、!=、~=7種匹配符號
"(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" 表示用單引號或雙引號括起來的轉義符或除反斜杠外的任意字符組合,或[標識]。其中\\3表示與(['\"])一致的字符,在此之所以用\\3表示,是因為(['\"])匹配的有可能是單引號也有可能是雙引號,\\3表示在當前位置匹配與(['\"])一致的字符,也就是要么是成對的單引號或成對的雙引號。3代表從正則表達式左側數過來第3對圓括號(括號后跟?:的以及\\(不算)。
\\] 表示右方括號
5、偽類選擇器
-
// Prefer arguments quoted,
-
// then not containing pseudos/brackets,
-
// then attribute selectors/non-parenthetical expressions,
-
// then anything else
-
// These preferences are here to reduce the number of selectors
-
// needing tokenize in the PSEUDO preFilter
-
pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
偽類基本格式如下:
":“ 表示冒號起頭
“(" + characterEncoding + ")" 表示偽類名稱
(?: \\( ( 第一組 | 第二組 | 第三組 ) \\) | ) 表示以圓括號括起來的三組匹配字符中的任意一組或沒有,該子表達式中最后的豎線相當於?的作用,表示前面的表達式可以沒有或有1個匹配項。
第一組:(['\"])((?:\\\\.|[^\\\\])*?)\\3 表示用單引號或雙引號括起來的轉義符或除反斜杠外的任意字符組合
第二組:((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*) 表示轉義字符或不包含反斜杠、圓括號和方括號的任意字符集合或符合屬性選擇器的字符集合
第三組:.* 表示任意多個除換行符和行結束符外的字符集合。
偽類是最復雜的正則表達式,其用於匹配偽類括號內選擇器的三個部分經過測試,其主要用於匹配下列情況:
第一組:用於匹配括號內用單引號或雙引號括起來的字符串,如::contains('hello')
第二組:用於匹配括號內除屬性、帶括號的偽類外的選擇器,即不存在嵌套的可能性的選擇器,如::eq(2)、:not(:first)
第三組:除上以外的所有選擇器。
另外,在此需要申明的一點是,偽類識別括號內信息采用的是貪婪方式進行匹配,所以,除第二組匹配出來的不可能超越自身所在偽類外(因不允許包含右括號),其余都可能跨越多個選擇器,例如:需要匹配的選擇器字符串如下:
-
選擇器一 :not( 'tile':first):contains('title');
-
選擇器二 :not(:first):eq( 4).class
對於選擇器一,可以匹配第一組,但是匹配內容不是'tile',而是'tile':first):contains('title',這就是貪婪方式導致的。
對於選擇器二,第一、二組子匹配項都不滿足,所以只好匹配第三項了,因此,其匹配內容是:first):eq(4,當然,這也是貪婪方式導致的。
在jQuery代碼中,將對匹配出來的內容進行進一步確認,獲取:not實際的結束位置,這個已超出了本標題的內容了,在此不再詳述了。
各位,若覺得本文章有用,請幫忙頂一下,多謝了!
若有問題,也可在評論里寫上。