【jQuery源码】preFilter
1 preFilter: { 2 "ATTR": function( match ) { 3 //属性名解码 4 match[1] = match[1].replace( runescape, funescape ); 5 6 // Move the given value to match[3] whether quoted or unquoted 7 //属性解码 8 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); 9 10 //若判断符为~=,则在属性值两边加上空格 11 if ( match[2] === "~=" ) { 12 match[3] = " " + match[3] + " "; 13 } 14 15 //返回前4个元素 16 return match.slice( 0, 4 ); 17 }, 18 19 "CHILD": function( match ) { 20 /* matches from matchExpr["CHILD"] 21 1 type (only|nth|...) 22 2 what (child|of-type) 23 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 24 4 xn-component of xn+y argument ([+-]?\d*n|) 25 5 sign of xn-component 26 6 x of xn-component 27 7 sign of y-component 28 8 y of y-component 29 */ 30 //match[1]:(only|first|last|nth|nth-last) 31 //match[2]: (child|last-child|of-type|last-of-type) 32 //match[3]: (even|odd) 33 //match[4]、match[5]: an+b中的a,b 34 35 //match[1]变成小写 36 match[1] = match[1].toLowerCase(); 37 38 //如果match[1]是"nth" 39 if ( match[1].slice( 0, 3 ) === "nth" ) { 40 // nth-* requires argument 41 //若选择器括号内没有有效参数,则抛出异常 42 if ( !match[3] ) { 43 Sizzle.error( match[0] ); 44 } 45 46 // numeric x and y parameters for Expr.filter.CHILD 47 // remember that false/true cast respectively to 0/1 48 /* 49 * 下面先以nth-child()为例介绍一下语法,以便更好的理解下面代码的作用 50 * nth-child允许的几种使用方式如下: 51 * :nth-child(even) 52 * :nth-child(odd) 53 * :nth-child(3n) 54 * :nth-child(+2n+1) 55 * :nth-child(2n-1) 56 * 下面代码中赋值号左侧的match[4]、match[5]用于分别记录括号内n前及n后的数值,包括正负号 57 * 对于:nth-child(even)和:nth-child(odd)来说,match[4]为空, 58 * 所以返回 2 * (match[3] === "even" || match[3] === "odd")的计算结果 59 * 因为在js中true=1,false=0,所以(match[3] === "even" || match[3] === "odd")等于1 60 * 因此,2 * (match[3] === "even" || match[3] === "odd")的计算结果为2 61 * 62 * 等号右侧的“+”的作用是强制类型转换,将之后的字符串转换成数值类型 63 */ 64 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 65 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 66 67 // other types prohibit arguments 68 //若非nth起头的其它CHILD类型选择器带有括号说明,则抛出异常 69 } else if ( match[3] ) { 70 Sizzle.error( match[0] ); 71 } 72 73 return match; 74 }, 75 76 "PSEUDO": function( match ) { 77 var excess, 78 unquoted = !match[6] && match[2]; 79 80 if ( matchExpr["CHILD"].test( match[0] ) ) { 81 return null; 82 } 83 84 // Accept quoted arguments as-is 85 if ( match[3] ) { 86 match[2] = match[4] || match[5] || ""; 87 88 // Strip excess characters from unquoted arguments 89 } else if ( unquoted && rpseudo.test( unquoted ) && 90 // Get excess from tokenize (recursively) 91 (excess = tokenize( unquoted, true )) && 92 // advance to the next closing parenthesis 93 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 94 95 // excess is a negative index 96 match[0] = match[0].slice( 0, excess ); 97 match[2] = unquoted.slice( 0, excess ); 98 } 99 100 // Return only captures needed by the pseudo filter method (type and argument) 101 return match.slice( 0, 3 ); 102 } 103 },