(tokens)
| 1868 | //Sizzle巧妙的就是它没有直接将拿到的“分词”结果与Expr中的方法逐个匹配逐个执行, |
| 1869 | //而是先根据规则组合出一个大的匹配方法,最后一步执行。但是组合之后怎么执行的 |
| 1870 | function matcherFromTokens(tokens) { |
| 1871 | var checkContext, matcher, j, |
| 1872 | len = tokens.length, |
| 1873 | leadingRelative = Expr.relative[tokens[0].type], |
| 1874 | implicitRelative = leadingRelative || Expr.relative[" "], //亲密度关系 |
| 1875 | i = leadingRelative ? 1 : 0, |
| 1876 | |
| 1877 | // The foundational matcher ensures that elements are reachable from top-level context(s) |
| 1878 | // 确保这些元素可以在context中找到 |
| 1879 | matchContext = addCombinator(function(elem) { |
| 1880 | return elem === checkContext; |
| 1881 | }, implicitRelative, true), |
| 1882 | |
| 1883 | matchAnyContext = addCombinator(function(elem) { |
| 1884 | return indexOf.call(checkContext, elem) > -1; |
| 1885 | }, implicitRelative, true), |
| 1886 | |
| 1887 | //这里用来确定元素在哪个context |
| 1888 | matchers = [ |
| 1889 | function(elem, context, xml) { |
| 1890 | return (!leadingRelative && (xml || context !== outermostContext)) || ( |
| 1891 | (checkContext = context).nodeType ? |
| 1892 | matchContext(elem, context, xml) : |
| 1893 | matchAnyContext(elem, context, xml)); |
| 1894 | } |
| 1895 | ]; |
| 1896 | |
| 1897 | for (; i < len; i++) { |
| 1898 | // Expr.relative 匹配关系选择器类型 |
| 1899 | // "空 > ~ +" |
| 1900 | if ((matcher = Expr.relative[tokens[i].type])) { |
| 1901 | //当遇到关系选择器时elementMatcher函数将matchers数组中的函数生成一个函数 |
| 1902 | //(elementMatcher利用了闭包所以matchers一直存在内存中) |
| 1903 | matchers = [addCombinator(elementMatcher(matchers), matcher)]; |
| 1904 | } else { |
| 1905 | //过滤 ATTR CHILD CLASS ID PSEUDO TAG |
| 1906 | matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); |
| 1907 | |
| 1908 | // Return special upon seeing a positional matcher |
| 1909 | //返回一个特殊的位置匹配函数 |
| 1910 | //伪类会把selector分两部分 |
| 1911 | if (matcher[expando]) { |
| 1912 | // Find the next relative operator (if any) for proper handling |
| 1913 | // 发现下一个关系操作符(如果有话)并做适当处理 |
| 1914 | j = ++i; |
| 1915 | for (; j < len; j++) { |
| 1916 | if (Expr.relative[tokens[j].type]) { //如果位置伪类后面还有关系选择器还需要筛选 |
| 1917 | break; |
| 1918 | } |
| 1919 | } |
| 1920 | return setMatcher( |
| 1921 | i > 1 && elementMatcher(matchers), |
| 1922 | i > 1 && toSelector( |
| 1923 | // If the preceding token was a descendant combinator, insert an implicit any-element `*` |
| 1924 | tokens.slice(0, i - 1).concat({ |
| 1925 | value: tokens[i - 2].type === " " ? "*" : "" |
| 1926 | }) |
| 1927 | ).replace(rtrim, "$1"), |
no test coverage detected