jQuery选择器源码解读(五):tokenize的解析过程(4)


tokens.push({ 
    value : matched, 
    type : type, 
    matches : match 


 创建一个新对象{ value:
":contain('span')", type:"PSEUDO", matches: ["contain", "span"] },并将该对象压入tokens数组。

复制代码 代码如下:


soFar = soFar.slice(matched.length); 

soFar变量删除":contain('span')",此时,soFar="):eq(3)",之后,直至for循环结束,且再次执行while循环,也没有一个有效选择器,故退出while循环。

复制代码 代码如下:


return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : 
    tokenCache(selector, groups).slice(0); 

由于此时parseOnly = true,故返回此时soFar的长度6,继续执行preFilters["PSEUDO"]的代码

复制代码 代码如下:


 else if (unquoted 
        && rpseudo.test(unquoted) 
        && (excess = tokenize(unquoted, true)) 
        && (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length) 
 

将6赋予excess变量,然后由代码
 

复制代码 代码如下:


 excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length 
 

计算出:not选择器结束位置(即右括号位置)22

复制代码 代码如下:


match[0] = match[0].slice(0, excess); 
match[2] = unquoted.slice(0, excess); 

分别计算出完整的:not选择器字符串(match[0])和其括号内的字符串(match[2]),分别等于:

match[0] = ":not(.class:contain('span'))"

match[2] = ".class:contain('span')"

复制代码 代码如下:


return match.slice(0, 3);

返回match中前三个元素的副本。
回到tokenize函数,此时match = [":not(.class:contain('span'))", "not", ".class:contain('span')"]

复制代码 代码如下:


matched = match.shift();

移除match中的第一个元素":not(.class:contain('span'))",并将该元素赋予matched变量,此时matched="":not(.class:contain('span'))"",
match = ["not", ".class:contain('span')"]

复制代码 代码如下:


tokens.push({ 
    value : matched, 
    type : type, 
    matches : match 

创建一个新对象{ value: ":not(.class:contain('span'))"", type:"PSEUDO", matches:  ["not", ".class:contain('span')"]  },并将该对象压入tokens数组。此时tokens共有两个元素分别是div和not选择器。

复制代码 代码如下:


soFar = soFar.slice(matched.length); 

soFar变量删除":not(.class:contain('span'))",此时,soFar=":eq(3)",结束本次for循环后,再次回到while循环,同样方式,获取tokens的第三个元素eq选择器,过程与not一致,这里就不再细讲了。最后的groups的结果如下:
group[0][0] = {value: "div", type: "TAG", matches: ["div"]  }

group[0][1] = {value: ":not(.class:contain('span'))", type: "PSEUDO", matches: ["not", ".class:contain('span')"] }

group[0][2] = {value: ":eq(3)", type: "PSEUDO", matches: ["eq", "3"] }

复制代码 代码如下:


return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : 
    tokenCache(selector, groups).slice(0); 

由于parseOnly = undefined,所以执行tokenCache(selector, groups).slice(0),该语句将groups压入缓存,并返回其副本。
由此,完成了所有的解析,或许有人会问,这里第二个元素并没有解析出来呀,是的,这个需要在实际运行中再次解析。当然,这里若可以将刚才解析."class:contain('span')):eq(3"时,将有效选择器的结果保存到缓存内,那么就可以避免再次解析,提高执行速度。但这也仅仅提高了当前这次运行速度。因为在执行过程中,对".class:contain('span')"再次提交解析时,会存入缓存。

至此,整个执行过程已经全部结束。

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgjpwf.html