標籤:style blog class code c java
上篇說道,tokenize方法會把selector分割成一個個selector邏輯單元(如div>a是三個邏輯單元 ‘div‘,‘>‘,‘a‘)並為之片段賦予對應類型的過濾函數。
for ( type in Expr.filter ) { if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || (match = preFilters[ type ]( match ))) ) { matched = match.shift(); tokens.push({ value: matched, type: type, matches: match }); soFar = soFar.slice( matched.length ); } }然後選出最後selector邏輯單元(是指由需要內容相關的選取器,如id,tag,class等)所對應的元素集作為從右向左(一般情況)過濾的候選元素集,match(正則擷取的群組)是selector邏輯片段的解析結果(如[arr="111"]根據正則解析為arr,",=,111 ),在selector邏輯片段是ATTR、CHILD、PSEUDO是需要調用preFilter對match進行修正.
preFilter: { //match是擷取的群組 //假設:[arr^=‘val‘] "ATTR": function( match ) { //attr的第一個捕獲 組是arr,將其中的轉碼變成原來的字元 match[1] = match[1].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted // 將val放到擷取的群組3裡,原來的擷取的群組3捕獲‘或" match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); //如果擷取的群組2是~=,在match[3]前後加空格,以方便匹配單個單詞 if ( match[2] === "~=" ) { match[3] = " " + match[3] + " "; } //match[0] = ‘[arr^=‘val‘]‘ //match[1] = ‘arr‘ //match[2] = ‘=‘ //match[3] = ‘111‘ return match.slice( 0, 4 ); }, "CHILD": function( match ) { /* 例如nth-child(-2n+1)的擷取的群組 mathc[1] nth mathc[2] child mathc[3] 2n+1 mathc[4] 2n mathc[5] - mathc[6] 2 mathc[7] + mathc[8] 1 */ match[1] = match[1].toLowerCase(); // nth必須需要參數 if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument if ( !match[3] ) { Sizzle.error( match[0] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 // xn + y // 將even,odd修正為xn+y,match[4]修正為+-x match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); // 將match[5]替換為+-y match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); // other types prohibit arguments // 除nth外其他類型禁止參數 } else if ( match[3] ) { Sizzle.error( match[0] ); } // match[0] :nth-child(-2n+1) // match[1] nth // match[2] child // match[3] -2n+1 // match[4] -2 // match[5] 1 // match[6] 2 // match[7] + // match[8] 1 return match; }, /** * match[1] :後偽類類型 * match[2] 偽類參數 * match[3] 參數中的‘或者" * match[4] 除去‘或"的偽類 */ "PSEUDO": function( match ) { var excess, unquoted = !match[5] && match[2]; //是CHILD偽類,返回null if ( matchExpr[ "CHILD"].test( match[0] ) ) { return null; } // Accept quoted arguments as-is // 參數有引號 //將match[2]替換為無引號的match[4]參數 if ( match[3] && match[4] !== undefined ) { match[2] = match[4]; // Strip excess characters from unquoted arguments // 除去帶引號的參數的多餘字元 } else if ( unquoted && rpseudo.test( unquoted ) && // Get excess from tokenize (recursively) //excess多餘字元的長度 (excess = tokenize( unquoted, true )) && //excess多餘參數的索引位置,excess是個負值,以便截取到多餘字元之前 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { // excess is a negative index match[0] = match[0].slice( 0, excess ); match[2] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) return match.slice( 0, 3 ); } }