1、空白
1.
// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
2.
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等标识符的判断,故此处把它翻译成标识符。
1.
2.
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、标识
1.
// Loosely modeled on CSS identifier characters
2.
// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
3.
// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
4.
identifier = characterEncoding.replace( "w", "w#" ),
这里为何需要加个#,不得而知,即便查了它给出的标准文档,也没有找到原因,且标准中标识符并没有允许使用#字符。哪位找到原因了,请分享一下。而且identifier事实上用于值得判断而非标识符的判断,就我自己仅会在href中使用#字符,故推测是否用于支持对href值的判断,故加了这个#。
4、属性选择器
1.
2.
attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3.
"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
属性基本格式如下:
[ 属性名称 匹配符号 值 ]
举例如下:
[ title != "hello" ]
上述属性选择器表示title属性值不等于hello
正则表达式从左到右依次解释如下:
"\\[" 表示左方括号
whitespace + "*" 表示前后两者之间的任意多个空白字符,后同
"*(" + characterEncoding + ")" 表示属性名称
(?:([*^$|!~]?=) 表示=、*=、^=、$=、|=、!=、~=7种匹配符号
"(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)"
表示用单引号或双引号括起来的转义符或除反斜杠外的任意字符组合,或[标识]。其中\\3表示与(['\"])一致的字符,在此之所以用\\3表示,是因为(['\"])匹配的有可能是单引号也有可能是双引号,\\3表示在当前位置匹配与(['\"])一致的字符,也就是要么是成对的单引号或成对的双引号。3代表从正则表达式左侧数过来第3对圆括号(括号后跟?:的以及\\(不算)。
5、伪类选择器
1.
// Prefer arguments quoted,
2.
// then not containing pseudos/brackets,
3.
// then attribute selectors/non-parenthetical expressions,
4.
// then anything else
5.
// These preferences are here to reduce the number of selectors
6.
// needing tokenize in the PSEUDO preFilter
7.
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实际的结束位置,这个已超出了本标题的内容了,在此不再详述了。