(jquery1.6.1版本)假设有一个html文档中存在多个<h1>标签元素,那么当我们敲入$("h1")后在jQuery内部将会执行怎样的逻辑呢?

分析jQuery构造函数我们同样定位到find( selector )方法,这个方法是jQuery的实例方法,代码如下:(5137行)

 find: function( selector ) {var self = this,i, l;if ( typeof selector !== "string" ) {return jQuery( selector ).filter(function() {for ( i = 0, l = self.length; i < l; i++ ) {if ( jQuery.contains( self[ i ], this ) ) {return true;}}});}var ret = this.pushStack( "", "find", selector ),length, n, r;for ( i = 0, l = this.length; i < l; i++ ) {length = ret.length;jQuery.find( selector, this[i], ret );if ( i > 0 ) {// Make sure that the results are uniquefor ( n = length; n < ret.length; n++ ) {for ( r = 0; r < length; r++ ) {if ( ret[r] === ret[n] ) {ret.splice(n--, 1);break;}}}}}return ret;},

我们暂不考虑其他调用的场景,只专注于selector参数为string类型时的逻辑。整体上调用流程是遵循jQuery一致的风格:实例方法"find(selector)"调用类方法"jQuery.find( selector, this[i], ret );",类方法find直接指向Sizzle构造函数"jQuery.find = Sizzle;"。当然还有一些其他的逻辑,如返回对象的构造、去重过滤等。

这时需要定位到Sizzle的构造函数,这时问题来了,Sizzle的定义不止一处,一处(3706行)定义是通用的,也是传统的,逻辑较为复杂,一处(4807行)定义在document.querySelectorAll存在时重载并复用传统定义。本文分析的是重载的相对简单的Sizzle定义。

     Sizzle = function( query, context, extra, seed ) {context = context || document;// Only use querySelectorAll on non-XML documents// (ID selectors don't work in non-HTML documents)if ( !seed && !Sizzle.isXML(context) ) {// See if we find a selector to speed upvar match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {// Speed-up: Sizzle("TAG")if ( match[1] ) {return makeArray( context.getElementsByTagName( query ), extra );// Speed-up: Sizzle(".CLASS")} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {return makeArray( context.getElementsByClassName( match[2] ), extra );}}if ( context.nodeType === 9 ) {// Speed-up: Sizzle("body")// The body element only exists once, optimize finding itif ( query === "body" && context.body ) {return makeArray( [ context.body ], extra );// Speed-up: Sizzle("#ID")} else if ( match && match[3] ) {var elem = context.getElementById( match[3] );// Check parentNode to catch when Blackberry 4.6 returns// nodes that are no longer in the document #6963if ( elem && elem.parentNode ) {// Handle the case where IE and Opera return items// by name instead of IDif ( elem.id === match[3] ) {return makeArray( [ elem ], extra );}} else {return makeArray( [], extra );}}try {return makeArray( context.querySelectorAll(query), extra );} catch(qsaError) {}// qSA works strangely on Element-rooted queries// We can work around this by specifying an extra ID on the root// and working up from there (Thanks to Andrew Dupont for the technique)// IE 8 doesn't work on object elements} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {var oldContext = context,old = context.getAttribute( "id" ),nid = old || id,hasParent = context.parentNode,relativeHierarchySelector = /^\s*[+~]/.test( query );if ( !old ) {context.setAttribute( "id", nid );} else {nid = nid.replace( /'/g, "\\$&" );}if ( relativeHierarchySelector && hasParent ) {context = context.parentNode;}try {if ( !relativeHierarchySelector || hasParent ) {return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );}} catch(pseudoError) {} finally {if ( !old ) {oldContext.removeAttribute( "id" );}}}}return oldSizzle(query, context, extra, seed);};

在传递给Sizzle函数的四个参数( query, context, extra, seed )中,当context参数和seed参数满足条件"if ( !seed && !Sizzle.isXML(context) )"时将执行重载的Sizzle逻辑,否则执行传统Sizzle逻辑。这里同样用一个正则表达式对象"/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/"对选择符参数query执行匹配,这个正则对象有三个分组,分别捕获tag/class/id,也就是说重载的Sizzle函数功能上支持这三种最基本的选择器(尽管实际中#id选择符在jQuery构造函数中已经处理过了,理论上走不到这个地方来)。

当分组一存在时,执行tag选择器逻辑;当分组二存在时,执行class选择器逻辑。可以看到,对于这两种选择符,背后的逻辑回到原生dom的基本api上了:context.getElementsByTagName( query )、context.getElementsByClassName( match[2] ),当然,就像id选择符一样,Sizzle返回的对象集合肯定也不会是原始dom元素集合,所以makeArray函数的功能就是把选择出来的原生dom元素集合inject到jQuery对象extra(第三个参数)中去:(4561行)

var makeArray = function( array, results ) {array = Array.prototype.slice.call( array, 0 );if ( results ) {results.push.apply( results, array );return results;}return array;
};

makeArray函数的逻辑比较简单:接受两个参数,第一个是待处理array like对象,第二个是待扩展对象,不传递第二个对象时,直接将array like对象转换为真正的array对象,否则将转换后的真正的array对象inject到第二个参数jQuery对象中去。

简单的单纯的TAG选择器和CLASS选择器执行逻辑就是这样的,相对而言还是比较简单的,后续分析复杂的组合的选择器执行逻辑,也即真正的Sizzle核心。

jQuery选择器探究:TAG选择器和CLASS选择器相关推荐

  1. jQuery学习笔记(一)——基础选择器、过滤选择器、表单选择器

    $()就是jQuery中的函数,它的功能是获得()中指定的标签元素.如示例中$("p")会得到一组P标签元素,其中"p"表示CSS中的标签选择器.$()中的() ...

  2. [jQuery] jQuery是通过哪个方法和Sizzle选择器结合的?

    [jQuery] jQuery是通过哪个方法和Sizzle选择器结合的? 通过创建一个div元素,检测被传入的fn是否被当前浏览器支bai持 function assert( fn ) { var d ...

  3. 小汤学编程之jQuery学习day01——简介、入门、选择器

    一.简介 1.下载     2.导入 二.入门 1.jQuery对象     2.jQuery对象与js对象相互转换     3.页面载入 三.选择器 1.基本选择器     2.层级选择器      ...

  4. jQuery学习笔记(二)使用选择器一

    jQuery选择器是jQuery框架的基础,jQuery对事件的处理.DOM操作.CSS动态控制.Ajax通信.动画设计都是在选择器基础上进行的 注意,在jQuery中通过各种选择器和方法获取的结果集 ...

  5. JQuery入门总结(三)【选择器、方法、Json】

    l两种方式:[index]和.get(index) l1.JQuery对象内部包含一个数组对象,可以通过[index]的方法,来得到相应的DOM对象 var $txtName=$("#txt ...

  6. html5复合选择器,web前端练习31----Css,选择器(基本选择器,复合选择器,属性选择器,伪类,伪元素,优先级,雪碧图练习)...

    参考文档:https://man.ilovefishc.com/css3/ 一.基本选择器: 1通配符选择器 * 2元素选择器 element 3类选择器 .class 4id选择器 #id 5内联样 ...

  7. 《HTML 5与CSS 3权威指南(第3版·下册)》——19.4.2 E:enabled伪类选择器与E:disabled伪类选择器...

    19.4.2 E:enabled伪类选择器与E:disabled伪类选择器 q E:enabled伪类选择器用来指定当元素处于可用状态时的样式. q E:disabled伪类选择器用来指定当元素处于不 ...

  8. html选择器有哪些child,css3选择器child有哪些?css3选择器child用法详解

    本篇文章给大家带来的内容是关于css3选择器child有哪些?css3选择器child用法详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 对于CSS3的结构伪类选择器,为了更好地 ...

  9. [css] 为什么说css中能用子代选择器的时候不要用后代选择器?

    [css] 为什么说css中能用子代选择器的时候不要用后代选择器? 选择从右到左依次解析匹配,所以后代选择器会去找它的所有父级, 而子代选择器只会选择直接的父级:减少匹配次数,提高效率 个人简介 我是 ...

  10. html四种选择器的特点,css四种选择器总结

    css 在网页开发中扮演着重要的角色,被誉为网页开发的三剑客,如果说html是人的外在器官部分,那css无疑是各个器官组成在一起然后表现出来,css又称样式重叠在网页排版布局中的地位举足轻重. 做为后 ...

最新文章

  1. 上海天氣情況及空氣質量指數
  2. 逻辑分析仪上位机DSview的简单触发设置
  3. 济南泉水与城市生态主题 第四届泉水文化论坛第二次会议
  4. REVERSE-PRACTICE-BUUCTF-25
  5. json 转换 java odl_opendaylight:如何查看配置数据库
  6. 鸡兔同笼(一道明显的体现cin和cout运行较慢的特点)
  7. 内存延时cl_内存延迟和内存时序有什么关系?内存速率和时钟周期| Crucial(英睿达)...
  8. python常用模块介绍
  9. 村上春树 --《当我谈跑步时,我谈些什么》句子摘录​
  10. Hadoop介绍和环境配置
  11. Java中Arrays.sort()的三种常用用法(自定义排序规则)
  12. 嵌入式系统课堂小结5
  13. 网站php挂马从哪里挂的,寻找PHP(网站)挂马,后门
  14. Intellij IDEA神器那些让人爱不释手的小技巧
  15. IEEE 754标准
  16. 图像处理之Hobject与Mat互转
  17. Grapher class scatter legend
  18. java沙漏_(java)五大常用算法
  19. 牛客-埃森哲杯第十六届上海大学程序设计联赛-A-Wasserstein Distance
  20. Hadoop-HDFS的数据读写过程(详细过程与图解)

热门文章

  1. 每日一句:day01——From Zero To Hero
  2. 【零基础】带你学C带你飞
  3. ubuntu11 下安装86五笔输入法
  4. IT招聘网站(程序员跳槽指南) 1
  5. steam你画我猜中文版
  6. 一个可大规模悄无声息窃取淘宝/支付宝账号与密码的漏洞 -(埋雷式攻击附带视频演示)
  7. Vitis-Ai 3.0 板卡镜像制作、模型量化编译教程
  8. 聚丙烯酰胺在造纸厂都有哪些用途?
  9. 用canvas做视频截图遇到的坑(已填坑)
  10. linux报表系统架构,综合报表系统设计方案.doc