JQuery日記_5.14 Sizzle選擇器(七)


上篇說道,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 );
            }
      }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章