Sizzle引擎--原理与实践(三)
查找的入口对应的是Sizzle.find方法,
Sizzle.find = function( expr, context) {}
expr :查找的表达式
context :查找的范围
find的步骤
第一步:判断主要集合,方法说过了,依次匹配,顺序就是ID --> NAME --> TAG
第二步:(1)当有类型被匹配时,调用相应的方法,获取集合set。(2)当ID,NAME,TAG全部不匹配时,获取context范围内的全部元素集合set
第三步:去除expr中已经匹配的部分,返回结果{expr : expr,set : set}
因此,Sizzle.find的大致代码流程是
Sizzle.find = function( expr, context, isXML ) { for ( i = 0, len = Expr.order.length; i < len; i++ ) { var type = Expr.order[i]; if((match = Expr.leftMatch[ type ].exec( expr ))){ // 对应第一步 if((set = Expr.find[ type ]( match, context ))!=null){ //对应第二步(1) expr = expr.replace( Expr.match[ 'ID' ], "" ); //对应第三步 break; } } } if(!set){//对应第二步(2) set = context.getElementsByTagName( "*" ); } return {expr : expr,set : set} }
实例说明:
<input type="radio" id="a" name="gender" value="man" class="default" /><label for="a" >男</label> <input type="radio" id="b" name="gender" value="man" class="default" /><label for="b">女</label> <input type="checkbox" id="c" name="gender" value="man" /><label for="c">人妖</label> var set; var expr = 'input[class*="default"]'; var match = Expr.leftMatch[ 'ID' ].exec( expr ) var left = match[1]; match.splice( 1, 1 ); set = Expr.find[ 'ID' ]( match, document); if ( set != null ) { expr = expr.replace( Expr.match[ 'ID' ], "" ); } if ( !set ) { set = typeof document.getElementsByTagName !== "undefined" ?document.getElementsByTagName( "*" ) :[]; } Expr.find['ID'] = function( match, context ) { if ( typeof context.getElementById !== "undefined") { var m = context.getElementById(match[1]); return m && m.parentNode ? [m] : []; } } console.log({ set: set, expr: expr });
因此从上面的实例来看,Sizzle.find并不是执行查找功能的部分,而是主要起了一个分发器的作用,
将不同的选择表达式分发到不同的更专一的查找器上面。上面的例子中就是将具体查找分发给Expr.find[ 'ID' ]
具体代码分析:
Sizzle.find = function( expr, context, isXML ) { var set, i, len, match, type, left; if ( !expr ) { //如果没有选择表达式,直接返回空集合 return []; } for ( i = 0, len = Expr.order.length; i < len; i++ ) {//用来判断应该选用哪个查找器,对应的顺序是[ "ID", "NAME", "TAG" ]; type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { //碰到符合条件的匹配 left = match[1]; match.splice( 1, 1 ); //因为leftMatch在match的头部添加了一个新的分组,所以现在提取第一个分组到left里面,然后删除这个分组 if ( left.substr( left.length - 1 ) !== "\\" ) { //参见讨论部分 match[1] = (match[1] || "").replace( rBackslash, "" ); \\检测,替换回车而已 set = Expr.find[ type ]( match, context, isXML ); \\转到相应的查找器执行查找程序 if ( set != null ) { //找到相应的结果,修剪expr expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { //[ "ID", "NAME", "TAG" ]中没有匹配的类型时候,直接返回context范围内的所有标签。 set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) :[]; } return { set: set, expr: expr }; }; Expr.order = [ "ID", "NAME", "TAG" ]; Expr.find = { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m && m.parentNode ? [m] : []; //这里注意优先级的问题。&&的优先级高于?:的优先级 } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } };
讨论
1、关于检测'\'的讨论【这个不知道对不对】
实例表达式expr = '\.className',CLASS匹配结果['\.className','.className'],此时原本的意图是'.'被转义,因此不应该作为class匹配,中止。
2、关于getElementById方法bug的讨论(源码1056行),
在某些浏览器里面,getElementById('test')会返回name值为test的a节点,因此会对查询结果产生干扰。比如:
<a name="test"></a><div id="test"></div>此时a节点在div前面,getElementById('test')回返回<a name="test"></a>而非预期中的<div id="test"></div>。
Sizzle也对此做了检测:
(function(){ // 先创建一个测试环境<div><a name="script20120215"></a></div> var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = "<a name='" + id + "'/>"; root.insertBefore( form, root.firstChild ); //检测getElementById的返回值,现获取了相应的节点之后,添加一步检测id属性,如果吻合就保存,不吻合就丢弃
if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } };
Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // 对于IE,需要释放刚才添加的DIV过程中各变量的缓存,便于垃圾回收 root = form = null; })();
相关推荐
在这个"jQuery中的Sizzle引擎分析demo"中,我们将深入探讨Sizzle的工作原理以及如何通过实例来理解它。 Sizzle引擎的设计目标是提供一个高性能的选择器解析和执行环境,它独立于jQuery之外,可以单独使用。Sizzle...
- 该框架的核心特性包括:选择器引擎(Sizzle)、类系统、对象继承、事件处理、动画效果、Ajax通信、JSON解析等。 - MVP框架选择MooTools作为基础,是因为它提供了构建复杂前端应用所需的基础设施。 2. **MVP模式...
### jQuery内核详解与实践 #### 一、引言 jQuery作为一款流行的JavaScript库,在前端开发领域具有举足轻重的地位。它简化了许多常见的JavaScript任务,如选择元素、动画、事件处理等,使得开发者能够更加高效地...
jQuery的选择器引擎Sizzle是其强大功能的关键之一。Sizzle支持CSS1-CSS3的选择器,并能有效地匹配和选取DOM元素。通过阅读源码,我们可以学习到如何编写高效的选择器,以及如何利用Sizzle实现复杂的DOM遍历。 3. *...
3. **选择器引擎Sizzle** - jQuery 1.9继续使用Sizzle作为其选择器引擎,能高效地选取DOM元素,支持CSS1至CSS3的选择器语法。 4. **DOM操作** - 包括`.append()`, `.prepend()`, `.before()`, `.after()`, `.remove...
学习资源与实践 要深入理解jQuery表单选择器的源码,可以阅读`jQuery源码`和`Sizzle源码`,同时结合实际项目进行实践。`第7章 表单选择器.pdf`文档可能是对这部分内容的一个详细讲解,建议配合源码阅读,加深理解...
其核心功能是提供一个高效的DOM操作接口,这主要得益于Sizzle选择器引擎的运用,使得jQuery能够快速准确地找到页面中的元素。 2. **选择器引擎Sizzle** Sizzle是一个独立于jQuery的选择器库,支持CSS1至CSS3的选择...
1. **选择器引擎Sizzle**:jQuery选择器是其强大功能的关键,它基于Sizzle引擎,能处理CSS1至CSS3的选择器。Sizzle引擎的高效解析和匹配算法是理解和优化jQuery性能的重要一环。 2. **DOM操作**:jQuery提供了丰富...
- **Sizzle选择器引擎**:jQuery内部使用的选择器引擎,它独立于jQuery核心之外,可以单独使用。 - **选择器解析过程**:从左到右逐个解析选择器中的每个元素,通过递归算法实现高效查找。 - **优化技巧**:利用缓存...
- **核心函数实现**:深入理解如选择器引擎Sizzle的工作原理,以及动画实现的细节。 通过阅读《jQuery权威指南》,读者将能够熟练运用jQuery进行高效的前端开发,并对jQuery的内部机制有深入的理解,提升Web开发...
随着对jQuery的深入,可以学习更高级的主题,如性能优化、插件开发、使用Sizzle选择器引擎等,进一步提升技能水平。 总结,jQuery是前端开发中强大的工具,通过学习其API和基本概念,可以大大提高开发效率,实现...
1. **CSS选择器引擎的改进**:jQuery 1.4中的Sizzle CSS选择器引擎得到了进一步的优化,提高了DOM查询的速度和效率。 2. **新的动画效果**:新增了更多的动画选项,如`slideToggle()`、`animate()`等,使得页面元素...
- **源码结构**: `jquery-1.4.4.js` 是 jQuery 1.4.4 版本的源码文件,它由多个核心模块组成,如选择器引擎(Sizzle)、事件处理、动画效果、Ajax 请求等。 - **选择器实现**: jQuery 1.4 使用 Sizzle 作为其选择...
jQuery的源码分析有助于开发者深入理解JavaScript的工作原理,提升JavaScript编程技能。 jQuery的源码主要分为几个部分: 1. **核心功能**: - `$` 函数是jQuery的核心,它是构造函数,接受一个DOM元素、HTML字符...
5. **选择器引擎Sizzle**:jQuery选择器的强大功能源于其内置的选择器引擎Sizzle,学习Sizzle的工作原理能帮助我们更好地利用jQuery选择器。 6. **API设计**:研究源码可以让我们理解jQuery是如何设计其API的,这对...
1. **选择器引擎(Sizzle)**:jQuery选择器是其强大功能的基础,它基于Sizzle引擎实现。Sizzle支持CSS1到CSS3的选择器,并且在没有浏览器内置querySelectorAll方法的情况下提供高性能的选择功能。 2. **链式调用**...
2. **jQuery选择器优化**:jQuery的选择器引擎Sizzle在处理复杂选择器时可能效率较低。优化选择器可以显著提升性能,例如尽量使用ID选择器而非类选择器,避免使用通配符选择器,以及减少嵌套选择器的使用。 3. **...
- **选择器引擎Sizzle**:jQuery选择器引擎Sizzle能解析CSS选择器并高效地找到匹配的DOM元素,它的实现涉及到正则表达式、缓存机制等。 - **链式调用**:jQuery对象是链式调用的基础,每个方法返回的都是jQuery...
Sizzle 引擎在源码中的实现涉及到字符串解析、DOM 遍历等复杂逻辑,是理解浏览器与 JavaScript 交互的关键。 7. **模块化设计** Prototype 使用模块化设计,将不同功能划分为独立的模块,如 `Form`、`Ajax`、`...