您的位置:首页 > Web前端 > JQuery

jquery 实现原理三:sizzle

2013-09-07 16:32 162 查看

一,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。

大体原理就是这样,具体到更下面的实现细节 暂时不想逐个看,如果本系列全部更新完之后有空闲时间 就再来完善这一章。 ^_^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息