最近在啃jQuery1.11源码,上来就遇到Sizzle这个jQuery的大核心,虽然已经清楚了Sizzle的用途,先绕过去也没事,但明知山有虎偏向虎山行才是我们要做的。

本文面向的阅读对象:正在学习Sizzle源码或有一定前端基础的同学们,可以一边看源码一边看这些文章进行验证,所以虽然我会分析源码中的正则表达式,有大量的注释,但不会讲正则表达式的基本用法!(我会给出一些链接,但不一定全面,请锻炼自主搜索的能力;为了避免歧义,本文的一些词会采用源码中的英文或js中的属性名)

Sizzle部分的代码已经啃完,本系列还有后续,这几天将会一一放出。本文主要分为两个部分:什么是SizzleSizzle的原理以及Sizzle结构概览

什么是Sizzle?

简单地来说,Sizzle是一个可以让你用CSS 选择器(selector)形式去获取DOM元素的引擎。

当我们想了解一个函数的用途和源码,必须先看它的要求和效果,就是输入和输出。

例如:你提供一个CSS selector 'html > body',Sizzle会返回给你一个数组,数组中只有一个元素body元素。

还有更复杂的CSS selector,比如 ‘body > div#main div.content input[type="text"]:nth(2)’,更多selector的用法请看

CSS selector用法

Sizzle的原理

我们先想想,如果让我们自己写一个Sizzle,先不考虑其中遇到的设计和细节问题,你会怎么做?

一个很自然的想法是,从父元素顺藤摸瓜往下一层层找下去。比如‘html > body’,我先找到nodeName为html的元素,再查看html的子元素里有没有一个nodeName为body的元素即可。

那么会面对几个问题:

你怎么知道在哪儿找html元素?于是我们需要一个查找上下文(context),默认为文档节点(document)

你怎么知道要找的是html元素而非h元素或者ht元素?所以我们需要一个词法分析器(tokenize),把selector切成三个词元(token)(一个数组(tokens)),[‘html’,'>','body']。(关于词法分析器,请学习编译原理相关知识)

难道处理‘html’和处理‘>’的方式是一样的?你怎么知道它要查找子元素?我们知道它们是不同的类型的词元(token),所以要记录词元的类型,上面的数组变为[{value:'html',type:'TAG'},{value:'>',type:'>'},{value:'body',type:'TAG'}],再交给对应的处理函数处理

难道每次我们都来上面这么一套么?我们经常用的不就是$('#id')或者$('.className')这样简单的用法么?所以我们可以把这种高频率的特殊情况拿出来先处理,处理不掉再用统一的方法处理。

上面这一套,从左往右匹配,从逻辑上来看是没什么问题的。那么思考下面这种情况

‘因为DOM是一种树形结构,所以越往下层,子节点是越多的,那么会有这样一种情况,body元素下有10000个div子元素,其中在5000的位置处有一个div的id为suprise。’这时给你一个内容为body > div#suprise的selector,你写的引擎会怎么处理?

继续用上面的方法,先找出body元素,然后一个个遍历body的子元素?

可以预见的是性能上的悲剧。。。

所以我们的Sizzle采用的是从右向左的匹配方式:

先调用getElementById('suprise')来获得该DOM元素(find过程)(因为浏览器低层目测会建立id的索引,所以获得非常快,即使需要遍历DOM树,也比我们自己遍历DOM树快),

再根据'>'判断其父元素是否是body元素(filter过程)即可。

OK,到这里为止性能方面有了一定的改进,再考虑一种情况:

'当我们需要查找的层次很深时,比如selector为body > div#main div.content input[type="text"]时,我们需要先找到待选(seed)的input,再依次过滤[type="text"]、div.content 、div#main 、body>,你们会怎么做?'

判断不同的token类型,再通过查找找到对应的过滤函数,并调用对应的过滤函数(filter),这是一个正常的想法。

那么我需要再用该selector来查找一次呢?(这是使用jQuery非常常见的场景)把上面的过滤过程再重复一遍?

于是另一种提升性能的方式出现了——缓存,把上面的多个过滤函数编译成一个匹配函数(matcher),然后以key-value的形式存在缓存里面,当我们再次查找同样的selector时,只需要把编译好的匹配函数(matcher)给取出来过滤用就可以了。

Sizzle的全部原理大致如上,至于特性检测、沙盒、bugfix这些细节,后面再说

Sizzle的结构概览

Sizzle的结构不用记,大致看看就好,后面会一一说到的,放一张图,来源:http://www.cnblogs.com/mufc-go/p/3299261.html

本文完。

剩下的下午健完身回来再发。

感谢@司徒正美(1.3版本源码分析),@nuysoft(1.7版本源码分析),@Aaron(2.03版本源码分析)给我的参考。

如果你喜欢这篇文章,请给我一个推荐,如果觉得有问题,请在评论里抽打我!

jQuery1.11源码分析(1)-----Sizzle源码概览[原创]的更多相关文章

  1. jQuery1.11源码分析(2)-----Sizzle源码中的正则表达式[原创]

    看完了上篇,对Sizzle有了一个大致的了解,我们接下来就可以正式开始啃Sizzle的源码了.上来就讲matcher难度太大,先来点开胃菜,讲讲Sizzle中的各个正则表达式的作用吧(本来还想讲初始化 ...

  2. jQuery1.11源码分析(3)-----Sizzle源码中的浏览器兼容性检测和处理[原创]

    上一章讲了正则表达式,这一章继续我们的前菜,浏览器兼容性处理. 先介绍一个简单的沙盒测试函数. /** * Support testing using an element * @param {Fun ...

  3. NIO 源码分析(05) Channel 源码分析

    目录 一.Channel 类图 二.begin 和 close 是什么 2.1 AbstractInterruptibleChannel 中的 begin 和 close 2.2 Selector 中 ...

  4. NIO 源码分析(02-2) BIO 源码分析 Socket

    目录 一.BIO 最简使用姿势 二.connect 方法 2.1 Socket.connect 方法 2.2 AbstractPlainSocketImpl.connect 方法 2.3 DualSt ...

  5. NIO 源码分析(02-1) BIO 源码分析

    目录 一.BIO 最简使用姿势 二.ServerSocket 源码分析 2.1 相关类图 2.2 主要属性 2.3 构造函数 2.4 bind 方法 2.5 accept 方法 2.6 总结 NIO ...

  6. [源码分析] 从实例和源码入手看 Flink 之广播 Broadcast

    [源码分析] 从实例和源码入手看 Flink 之广播 Broadcast 0x00 摘要 本文将通过源码分析和实例讲解,带领大家熟悉Flink的广播变量机制. 0x01 业务需求 1. 场景需求 对黑 ...

  7. drf的基本使用、APIView源码分析和CBV源码拓展

    cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ...

  8. Spring Ioc源码分析系列--Ioc源码入口分析

    Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...

  9. k8s client-go源码分析 informer源码分析(3)-Reflector源码分析

    k8s client-go源码分析 informer源码分析(3)-Reflector源码分析 1.Reflector概述 Reflector从kube-apiserver中list&watc ...

随机推荐

  1. WSTMall网站系统最新官方版

    WSTMall V1.0是在thinkphp 的经典版本3.2.2基础上进行优化开发的, TP 3.2.2不是thinkphp的一个最新的版本,却是thinkphp最金典的一个版本,正所谓站在巨人的肩 ...

  2. OpenStack 企业私有云的若干需求(10):OpenStack 的前景和钱景

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

  3. Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  4. 《Invert》开发日志00:缘起

    按照所有程序员的惯例,编号从0开始.本系列日志将记录一款独立游戏 发起->构思->设计->实现->完善->测试(如果需要)->上线->后期维护(如果有人玩) ...

  5. POJ3422 Kaka's Matrix Travels[费用流]

    Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9522   Accepted:  ...

  6. 简单的angular购物车商品小计

    <!DOCTYPE html> <html lang="en" ng-app="shopApp"> <head> <m ...

  7. css3伪类温故知新

    今天遇到一个问题.要求::after 和 ::before的 content:"content" 能够动态的进行变换,能被JavaScript操作. 百度了下,自己做了实验,发现有 ...

  8. iOS 关于字体根据不同屏幕尺寸等比适配的问题(zz)

    http://www.jianshu.com/p/5815e81abb52 背景 去年的六月份开始了一个新的项目,此项目支持的设备从4S开始一直到6+,也就是说屏幕的尺寸最小的320x480 最大的1 ...

  9. 【swift学习笔记】三.使用xib自定义UITableViewCell

    使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell,拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewc ...

  10. 淘宝WAP版小BUG分析

    前几天发现的一个淘宝WAP版的小BUG,就是用桌面版chrome看的时候产品评价中的图片显示不出来,都是图裂了. 这是什么原因呢?图片为什么会显示不出来呢?淘宝的技术人员.测试人员不可能没发现啊.开启 ...