jquery源码学习(二)sizzle部分

一,sizzle的基本原理

sizzle是jquery选择器引擎模块的名称,早在1.3版本就独立出来,并且被许多其他的js库当做默认的选择器引擎。
首先,sizzle最大的特点就是快。那么为什么sizzle当时其他引擎都快了,因为当时其他的引擎都是按照从左到右逐个匹配的方式来进行查找的,而sizzle刚好相反是从右到左找的。

举个简单的例子 “.a .b .c”来说明为什么sizzle比较快。这个例子如果按照从左到右的顺序查找,很明显需要三次遍历过程才能结束,即先在document中查找.a,然后再结果中查找.b,再在.b的结果中查找.c。
采用这种方式,其时间复杂度是 a*b*c,其实也就是时间复杂度 O(n3)。注意这里的O(n3)只算对dom的遍历查找,因为现对于对PO的操作这个是特别耗时。
下面再看看sizzle是怎么做的,sizzle是从右到左查找,也就是直接在页面中查找.c,这时会得到一个候选结果集seed,然后对seed的每一个结果把parents不符合.a .b的结果剔除掉,就是最终结果。这个过程实际上只对dom进行了一次遍历查找,剩下的过滤操作是沿着parent指针直接查找非常快速。可以认为这是一个时间复杂度O(n)的算法。
所以,可以看出只需要遍历查找一次dom的sizzle在理论上是有明显的速度优势的,当然实践检验也证明了这点。

二,sizzle的实现

 

1,首先调用Sizzle(selector, context)方法

     此方法做的事: 
     1.1 先设置上下文context,然后调用rquickExpr正则式来判断是不是简单的id/class/tag选择器,如果是则直接调用相应的方法就可以得到结果
     1.2 如果不是简单的选择器,则查看是否支持qsa(即querySelectorAll)方法,如果支持则调用querySelectorAll方法来取结果
     1.3 否则,没有任何捷径,则调用 select(selector, context, results, seed)

2, 调用select(selector, context, results, seed) 方法

     2.1 首先调用tokenize(selector)方法把selector分解成单个token
     2.2 如果没有种子seed,那么2.3
     2.3 如果分解出来的token只有一组,那么根据tokens从右往左查找seed,比如选择器是".a .b .c",那么先找到所有的.c元素存到候选集seed里,以后所要做的就是过滤掉seed中不符合的元素即可
     2.4 最后调用 compile(selector, match)(seed, context)剔除seed中不符合条件的元素即可

3, 调用 compile 方法

     此方法返回一个函数,这个函数被调用之后:
     3.1,对每一个seed中得元素调用matcher逐个过滤,把符合的结果存到results数组中。matcher方法的实现,参见4

4,matcher方法

     matcher的作用是,对候选集seed进行过滤,matcher的实现过程就是对一个元素不断向上找parentNode并且判断parentNode是不是满足条件,不满足条件的就返回false。

 

大体原理就是这样,具体到更下面的实现细节 暂时不想逐个看,如果本系列全部更新完之后有空闲时间 就再来完善这一章。 ^_^

jquery源码学习(二)sizzle部分 【转】,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。