选择器初窥

代码架构:

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. ExtJS3.4升级ExtJS4.2的问题汇总(转)

    ExtJS3.4升级ExtJS4.2的问题汇总 昨天心血来潮,想把自己用extjs3.4作为UI的一个原型升级到最新的extjs4.2.2. 几年前曾经将原型从2.1升级到3.4,对于extjs的版本 ...

  2. 判断浏览器增加标签 encodeURIComponent

    var Sys = {}; var ua = navigator.userAgent.toLowerCase(); var s; var lx; (s = ua.match(/msie ([\d.]+ ...

  3. webpy

    url处理 对于一个站点来说,URL 的组织是最重要的一个部分,因为这是用户看得到的部分,而且直接影响到站点是如何工作的,在著名的站点如:del.icio.us ,其URLs 甚至是网页界面的一部分. ...

  4. Zookeeper的安装和配置

    1.ZooKeeper 1.1 zk可以用来保证数据在zk集群之间的数据的事务性一致.2.如何搭建ZooKeeper服务器集群 2.1 zk服务器集群规模不小于3个节点,要求各服务器之间系统时间要保持 ...

  5. 主机windwo7+虚拟机centos如何配置虚拟机可以上网,且与主机互ping通

    /etc/sysconfig/network-scripts/ifcfg-eth0的配置如下: E=eth0PROTO=static#IPADDR=10.1.1.138IPADDR=192.168.0 ...

  6. Ubuntu14.04下SP_Flash_Tool_exe_Linux无法烧录

    1,用命令lsusb查看usb信息. 2,vim 20-mm-blacklist-mtk.rules 输入下面内容: ATTRS{idVendor}=="0e8d",ENV{ID_ ...

  7. android:分享 一个很强大的LOG开关---Log.isLoggable

    标签:android分享 一个很强大的log开 1.API亮点: 此API可以实现不更换APK,在出问题的手机上就直接能抓到有效log,能提升不少工作效率. 2.API介绍 最近在解决短信问题时,看到 ...

  8. css脱离文档流

    作者:张秋怡链接:http://www.zhihu.com/question/24529373/answer/29135021来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...

  9. 加密Web.Config配置文件

    protected void btnPassWord_Click(object sender, EventArgs e) { //加密 Configuration config = WebConfig ...

  10. space 管理

    输入:表空间名字 输出:表空间下的一个文件即退出 /tmp/.sql select name from v$database; set serveroutput on; declare i1 varc ...