选择器初窥

代码架构:

jQuery选择器可以依照传入数据的类型分为五大类:

  • 传入字符串:$("div"), $("#id"), $(".div1"),$(".div p.title")
  • 传入html代码:$("<div></div>"), $("<div>1</div><div>2</div>")
  • 传入对象:$(document), $(this)
  • 传入数组或对象字面量:$({}), $([])
  • 传入函数:$(function(){})

下面我们来看一下jQuery构造函数代码(jQuery-2.2.2第2832行起)的架构:

jQuery.fn.init = function(selector, context){
if(!selector){ // part1.处理$(null), $(undefined), $(false), $("") }
if(typeof selector == "string"){ // part2.匹配selector并将结果传入match中 }
if(match && (match[1] || !context)){ // part3.创建标签或按#id查询 }else{ // part4.处理复杂选择器 }
}
// 一些其他的不常见情况
else {...}
return jQuery.makeArray(selector, this);
}

可以发现jQ将代码依照selector的类型分为了几个部分。下面我们来依次分析这几部分的代码。

第一部分:检测没有传入值的情况

此段完整代码如下:

// HANDLE: $(""), $(null), $(undefined), $(false)
if ( !selector ) {
return this;
}

第二部分:匹配传入的字符串

此段完整代码如下:

if ( selector[ 0 ] === "<" &&selector[ selector.length - 1 ] === ">" &&selector.length >= 3 ) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];
} else {
match = rquickExpr.exec( selector );
}
// 匹配html标签或#id
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

通过分析rquickExpr正则表达式,我们可以得出在selector分别为以下几种值时返回值match的结构:

1. selector = "<div>"

match = [null, "<div>", null]

2. selector = "<div>content</div>"

match = [null, "<div>content</div>", null]

3. selector = "<div></div>content"

match = ["<div></div>content", "<div></div>", null]

4. selector = #id

match = [#id, null, #id]

第三部分:创建标签或者按#id查询

传入标签时:

此段完整代码如下:

// 如果是html标签
if ( match[ 1 ] ) {
// 如果传入的context是jQ对象,将其转换成原生对象
context = context instanceof jQuery ? context[0] : context; // 将传入的html字符串转换成节点数组并传入this中
jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true)); // 如果是$(html, props)的形式,则要设置对应属性或执行方法
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) { // 若 prop 的某一项是jQ方法
if (jQuery.isFunction(this[match])) {
this[match](context[match]); // 否则设置对应属性
} else {
this.attr(match, context[match]);
}
}
} return this;
}
// 匹配单标签
var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );

关键位置的语意都已在注释中讲解过了,下面主要介绍一下$.parseHTML和$.merge这两个方法在其中的应用:

jQuery.parseHTML( data [, context ] [, keepScripts ] )
  • data:需要被转换成节点的字符串
  • context:被转换的节点所存在的上下文。并没有太大用处,默认是document,在需要在iframe中进行操作时,也可以设成contentWindow。
  • keepScripts:布尔值。设置成true时允许将字符串中的<script>部分也转换成节点。
jQuery.merge(first, second)

我们经常用$.merge来进行数组的合并。在本例中需要强调的一点是,$.merge被用来将一个数组合并到类数组对象中。就像下面这样:

  var obj = {0: "hello", 1: "pansy", length: 2};
var arr = ["from", "arr"]; console.log($.merge(obj, arr)); // Object {0: "hello", 1: "pansy", 2: "from", 3: "arr", length: 4}

传入id时:

// HANDLE: $(#id)
else {
elem = document.getElementById( match[ 2 ] ); // Support: Blackberry 4.6
// gEBID returns nodes no longer in the document (#6963)
if ( elem && elem.parentNode ) { // Inject the element directly into the jQuery object
this.length = 1;
this[ 0 ] = elem;
} this.context = document;
this.selector = selector;
return this;
}

第四部分:处理复杂选择器

// 处理形如$(".class"), $("ul li+p")等等
if ( !context || context.jquery ) {
return ( context || root ).find( selector ); // 当传入上下文是原生对象时,调用构造函数返回jQ对象
} else {
return this.constructor( context ).find( selector );
}

此处复杂选择器全部借助$().find()方法实现,使用了sizzle引擎,我们稍后再进行介绍。

jQuery源码学习(2):选择器初窥的更多相关文章

  1. jquery源码学习(一)——jquery结构概述以及如何合适的暴露全局变量

    jQuery 源码学习是对js的能力提升很有帮助的一个方法,废话不说,我们来开始学习啦 我们学习的源码是jquery-2.0.3已经不支持IE6,7,8了,因为可以少学很多hack和兼容的方法. jq ...

  2. Hadoop源码学习笔记(3) ——初览DataNode及学习线程

    Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Config ...

  3. jquery源码学习笔记三:jQuery工厂剖析

    jquery源码学习笔记二:jQuery工厂 jquery源码学习笔记一:总体结构 上两篇说过,query的核心是一个jQuery工厂.其代码如下 function( window, noGlobal ...

  4. jQuery源码学习扒一扒jQuery对象初使化

    神奇的jQuery可以这样玩jQuery("#id").css()或 jQuery("#id").html() 这么玩jQuery("#id" ...

  5. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  6. jquery 源码学习(一)

    从上边的注释看,jQuery的源码结构相当清晰.条理,不像代码那般晦涩和让人纠结   1. 总体架构 1.1 自调用匿名函数 self-invoking anonymous function 打开jQ ...

  7. 读艾伦的jQuery的无new构建,疑惑分析——jquery源码学习一

    背景: 有心学习jquery源码,苦于自己水平有限,若自己研究,耗时耗力,且读懂之日无期. 所以,网上寻找高手的源码分析.再经过自己思考,整理,验证.以求有所收获. 此篇为读高手艾伦<jQuer ...

  8. jquery 源码学习(*)

    最近在做日志统计程序,发现对方的程序是在Jquery基础上进行开发的,而公司的网站的框架是prototype.而且我也早就想了解一下Jquery源码,故决定研究Jquery源码,模拟它的方法   Jq ...

  9. 菜鸟的jQuery源码学习笔记(前言)

    前言 相信任何一名前端开发人员或者是前端爱好者都对jQuery不陌生.jQuery简单易用,功能强大,特别是拥有良好的浏览器兼容性,大大降低了前端开发的难度,使得前端开发变得“平易近人起来”.自从本人 ...

随机推荐

  1. ==和equals的异同

    == 和 Equals 的区别 1. == 是一个运算符. 2.Equals则是string对象的方法,可以.(点)出来. 我们比较无非就是这两种 1.基本数据类型比较 2.引用对象比较 1.基本数据 ...

  2. L8,the best and the worst

    expressions: enter for 报名参加,只有作为参加的意思的时候才会用for enter the room进入房间 a little prize for the worst garde ...

  3. 一个appium 博客

    http://www.cnblogs.com/tobecrazy/category/699177.html appium Java控制Appium server start/stop 摘要: 相信很多 ...

  4. 12C 连接方式和 Oracle Easy Connect Naming method

    1.12C 连接方式 PDB is not an instance, so using SID in the connection string will not work. When the dat ...

  5. Warning: The Copy Bundle Resources build phase contains this target's Info.plist file 'yintingting_baisi/Info.plist'.

    处理方法: The INFOPLIST_FILE build setting specifies the name of the Info.plist associated with your tar ...

  6. PAT (Advanced Level) 1047. Student List for Course (25)

    简单题. #include<iostream> #include<cstring> #include<cmath> #include<algorithm> ...

  7. vc6 pbo 文件为空的解决方法

    使用Profile调试vc6应用程序的性能时,将生成pbo文件,今天在vc IDE中增加了命令行启动参数,导致profile无法生成pbo文件,进而无法生成性能报告. 解决方法: 去掉IDE中的命令行 ...

  8. mysql基础---日志文件

    一 基本日志文件 MYSQL有不同类型的日志文件(各自存储了不同类型的日志),从它们当中可以查询到MYSQL里都做了些什么,对于MYSQL的管理工作,这些日志文件是不可缺少的. 1.错误日志(The ...

  9. Android网络开发之Volley--Volley基本用法StringRequest(一)

    1.StringRequest用法 主要分为3步: (1).实例化一个RequestQueue对象 (2).设置StringRequest对象参数,并将StringRequest对象加入Request ...

  10. A标签中通过href和onclick传递的this对象

    在blog的后台管理中允许为一个分类添加一个地址,但是不好添加onclick事件.想传递当前对象给一个函数,于是就将这个URL写成"Javascript:shoControlSidebar( ...