1. 程式人生 > >詳解jQuery選擇器正則表示式

詳解jQuery選擇器正則表示式

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實際的結束位置,這個已超出了本標題的內容了,在此不再詳述了。

各位,若覺得本文章有用,請幫忙頂一下,多謝了!

若有問題,也可在評論裡寫上。