1 /**
  2  * select方法是Sizzle选择器包的核心方法之一,其主要完成下列任务:
  3  * 1、调用tokenize方法完成对选择器的解析
  4  * 2、对于没有初始集合(即seed没有赋值)且是单一块选择器(即选择器字符串中没有逗号),
  5  *    完成下列事项:
  6  *    1) 对于首选择器是ID类型且context是document的,则直接获取对象替代传入的context对象
  7  *    2) 若选择器是单一选择器,且是id、class、tag类型的,则直接获取并返回匹配的DOM元素
  8  *    3) 获取最后一个id、class、tag类型选择器的匹配DOM元素赋值给初始集合(即seed变量)
  9  * 3、通过调用compile方法获取“预编译”代码并执行,获取并返回匹配的DOM元素
 10  *
 11  * @param selector 已去掉头尾空白的选择器字符串
 12  * @param context 执行匹配的最初的上下文(即DOM元素集合)。若context没有赋值,则取document。
 13  * @param results 已匹配出的部分最终结果。若results没有赋值,则赋予空数组。
 14  * @param seed 初始集合
 15  */
 16 select = Sizzle.select = function( selector, context, results, seed ) {
 17     var i, tokens, token, type, find,
 18         compiled = typeof selector === "function" && selector,
 19         //在没有seed的时候,调用tokensize方法进行词法解析,结果放在match中
 20         //seed - 种子合集(搜索器搜到符合条件的标签),放入到这个初始集合seed中
 21         match = !seed && tokenize( (selector = compiled.selector || selector) );
 22
 23     results = results || [];
 24
 25     // Try to minimize operations if there is no seed and only one group
 26     //只有一组选择器,也就是选择器中没有逗号
 27     if ( match.length === 1 ) {
 28
 29         // Take a shortcut and set the context if the root selector is an ID
 30         //创建一个新的集合赋给tokens,确保原有集合不被更改
 31         tokens = match[0] = match[0].slice( 0 );
 32         /*
 33              * 若选择器是以id类型开始,且第二个是关系符(即+~>或空格),
 34              * 则获取id所属对象作为context继续完成后续的匹配
 35              *
 36              * 此处的条件判断依次为:
 37              * tokens.length > 2 :若tokens有两个以上的选择器
 38              * (token = tokens[0]).type === "ID" :第一个选择器的类型为ID(即以#开头的),
 39              * support.getById :支持getElementById函数
 40              * context.nodeType === 9 :context对象是document
 41              * documentIsHTML :当前处理的是HTML代码
 42              * Expr.relative[tokens[1].type] :第二个tokens元素是一个关系(即+~>或空格)
 43              * 在满足上面所有条件的情况下,执行if内的语句体
 44         */
 45         if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
 46                 support.getById && context.nodeType === 9 && documentIsHTML &&
 47                 Expr.relative[ tokens[1].type ] ) {
 48
 49             //查找id为matches[1]的元素
 50             context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
 51             if ( !context ) {
 52                 return results;
 53
 54             // Precompiled matchers will still verify ancestry, so step up a level
 55             } else if ( compiled ) {
 56                 context = context.parentNode;
 57             }
 58
 59             //去掉selector中第一个选择器
 60             selector = selector.slice( tokens.shift().value.length );
 61         }
 62
 63         // Fetch a seed set for right-to-left matching
 64         //其中: "needsContext"= new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
 65         //即是表示如果没有一些结构伪类,这些是需要用另一种方式过滤,在之后文章再详细剖析。
 66         //那么就从最后一条规则开始,先找出seed集合
 67         i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
 68         while ( i-- ) {
 69             token = tokens[i];
 70
 71             // Abort if we hit a combinator
 72             //如果遇到了关系选择器则终止循环,> + ~ 空
 73             if ( Expr.relative[ (type = token.type) ] ) {
 74                 break;
 75             }
 76             /*
 77                 先看看有没有搜索器find,搜索器就是浏览器一些原生的取DOM接口,简单的表述就是以下对象了
 78                 Expr.find = {
 79                     'ID'    : context.getElementById,
 80                     'CLASS' : context.getElementsByClassName,
 81                     'NAME'  : context.getElementsByName,
 82                     'TAG'   : context.getElementsByTagName
 83                 }
 84             */
 85             if ( (find = Expr.find[ type ]) ) {
 86                 // Search, expanding context for leading sibling combinators
 87                 // 尝试一下能否通过这个搜索器搜到符合条件的初始集合seed
 88                 if ( (seed = find(
 89                     token.matches[0].replace( runescape, funescape ),
 90                     rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
 91                 )) ) {
 92
 93                     // If seed is empty or no tokens remain, we can return early
 94                     //删除这条标签
 95                     tokens.splice( i, 1 );
 96                     selector = seed.length && toSelector( tokens );
 97                     //若当前选择器是否为空,把seed推入results,返回结果
 98                     if ( !selector ) {
 99                         push.apply( results, seed );
100                         return results;
101                     }
102                     //已经找到了符合条件的seed集合,此时前边还有其他规则,跳出去
103                     break;
104                 }
105             }
106         }
107     }
108
109     // Compile and execute a filtering function if one is not provided
110     // Provide `match` to avoid retokenization if we modified the selector above
111     ( compiled || compile( selector, match ) )(
112         seed,
113         context,
114         !documentIsHTML,
115         results,
116         rsibling.test( selector ) && testContext( context.parentNode ) || context
117     );
118     return results;
119 };

转载于:https://www.cnblogs.com/shytong/p/5351656.html

【jQuery源码】select方法相关推荐

  1. JQuery 源码解析资料

    2019独角兽企业重金招聘Python工程师标准>>> jQuery源码分析系列目录 jQuery源码解读-理解架构 jQuery源码解析(架构与依赖模块) jQuery v1.10 ...

  2. 深入学习jquery源码之jQuery的选择器引擎Sizzle(一)

    深入学习jquery源码之jQuery的选择器引擎Sizzle Sizzle是一个纯javascript CSS选择器引擎.jquery1.3开始使用sizzle,Sizzle一反传统采取了相反的Ri ...

  3. jQuery源码学习之Callbacks

    jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...

  4. js便签笔记(9)——解读jquery源码时记录的一些知识点

    近来一直利用业余时间在看jquery2.1.1源码,大约看了两千行了.平时看的时候,做了一些笔记,贴出来分享. 1. Array.prototype.slice.call 可以将伪数组转化为真正的数组 ...

  5. jQuery源码学习(1)——addClass

    最近比较闲,寻思着学习下jQuery源码,看了好多博客,很多都讲的比较详细.jQuery虽然只有那么200多K,但内容却比较丰富,对于我这样一个js菜鸟,看起来相当吃力.骨头太大,只能化整为零,从简单 ...

  6. Jquery源码分析-整体结构

    最近在学习Jquery的最新的源码,Jquery-3.3.1版本.网上有很多对jquery解析的文章.但是我还是要自己去尝试着看一篇jquery的源码.本系列博客用来记录其中的过程,并同大家分享.本次 ...

  7. jQuery 源码分析第一篇之入口源码

    目前阅读的是jQuery 1.11.3的源码,有参考nuysoft的资料.原来比较喜欢在自己的Evernote上做学习基类,并没有在网上写技术博客的习惯,现在开始学习JS的开源代码,想跟大家多交流,希 ...

  8. jQuery源码分析-each函数

    本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuer ...

  9. 【jQuery源码】整体架构

    jQuery源码可以精简为以下内容: 方框上面的代码根据Jq注释我们可以知道是对AMD规范的支持. jQuery整体上被包裹在一个匿名函数中,这个匿名函数再作为另一个匿名函数的参数被传入,形参fact ...

  10. jquery源码 DOM加载

    jQuery版本:2.0.3 DOM加载有关的扩展 isReady:DOM是否加载完(内部使用) readyWait:等待多少文件的计数器(内部使用) holdReady():推迟DOM触发 read ...

最新文章

  1. 全球首款搭载鸿蒙操作系统的设备是什么,全球首款搭载鸿蒙操作系统:舒华展示极智2代豪华商用跑步机...
  2. 设计模式 — 行为型模式 — 命令模式
  3. bom中的event以及一些window的API
  4. Bitcoin 中的挖矿算法(3) 挖矿算法代码说明
  5. js中字符串编码函数escape()、encodeURI()、encodeURIComponent()区别详解
  6. strcpy函数_错误更正(拷贝赋值函数的正确使用姿势)
  7. c语言链表复数实验,数据结构实验—复数计算器 大神提意见
  8. python爬虫【2021.02.01】
  9. matlab画2fsk频谱,2fsk信号调制解调频谱的matlab仿真
  10. Kubeflow:连接云计算和机器学习的“桥梁”
  11. 《Linux 系列》- 常用命令- 文件浏览命令]
  12. Unicode-GBK映射表下载。
  13. 螺旋模型(Spiral Model)
  14. java数字转大写_java实现数字转大写的方法
  15. K3S配置IPV6环境
  16. GenXus进行APP开发-全局颜色设计
  17. IDC数据:中国VR市场2017预计增幅将达441.2%
  18. 专利缴费后如何获取发票
  19. DetectGPT VS ChatGPT:AI反击战?
  20. C语言学习22.9.4

热门文章

  1. java程序在eclipse上运行和导出文件运行结果不同
  2. Ubuntu下配置samba实现文件夹共享
  3. 聊聊大厂面试官必问的 MySQL 锁机制
  4. 性能提升约 7 倍!Apache Flink 与 Apache Hive 的集成
  5. 记一次找因 Redis 使用不当导致应用卡死 bug 的过程
  6. 三大工厂模式的优缺点
  7. Java:Random.nextInt()
  8. Andoird --- Json 经典异常:org.json.JSONException: Unterminated string at character
  9. poi excel 隐藏标识_纳尼?Excel竟然自带项目管理模板
  10. vc设置窗口在另一个窗口前面_日常办公如何设置IE