选择器初窥

代码架构:

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. android 报错之noclassdeffounderror

    解决方案1: 导入第3方jar包问题,明明导入了jar但还是报java.lang.NoClassDefFoundError解决步骤:1.在Android项目根目录下新建一个lib文件夹:2.把你需要导 ...

  2. Linux学习 -- Shell编程 -- 正则表达式

    正则表达式与通配符 正则 -- 匹配字符串 -- 包含匹配     grep.awk.sed等 通配符 -- 匹配文件名 -- 完全匹配  ls.find.cp等 基础正则表达式

  3. U3D游戏开发基础

    向量: 1. 向量的长度,即向量的模.计算公式为向量各个分量的平方和,然后开平方. 在D3DX库中,方法为:FLOAT  D3DXVec3Length(CONST  D3DXVECTOR3 * pV) ...

  4. Chapter 1 First Sight——20

    After two classes, I started to recognize several of the faces in each class. 两节课之后,我开始记住了每节课的那几张脸. ...

  5. CentOS添加字体

    到Windows XP或者Vista下复制字体到CentOS 1.到Windows XP或者Vista下复制字体到CentOS 雅黑:msyh 黑体:SimHei 宋体:SimSun 华文细黑:STX ...

  6. hdu_2159_FATE(完全背包)

    题目连接:hdu_2159_FATE 题意:完全背包的题意 题解:把杀敌数看成背包的容量,维护一个经验的最大值,我是多开一维来记录最大的忍耐度,当然你也可以直接开一位,并记录忍耐度,最后扫一遍 #in ...

  7. Linux批量替换文本,文件夹内所有文本内容

    1.替换文件夹内所有文件匹配的字符串 sed -i "s/旧内容/新内容/g" `grep 旧内容 -rl 文件夹路径` 例如将/var/www/test文件夹下的所有文件内容中的 ...

  8. apache禁止公网IP访问的配置

    由于最近在配置负载均衡环境 外网使用Nginx做代理,分发到Apache服务器上,所以不希望Apache配置的服务被外网访问,只希望内网Nginx访问,所以只能使用局域网IP访问 配置方法: 打开Ap ...

  9. linux下libreoffice安装测试

    一.Linux安装 wget http://download.documentfoundation.org/libreoffice/stable/4.4.6/rpm/x86_64/LibreOffic ...

  10. Activity与Service之间交互并播放歌曲的实现代码

    Activity与Service之间交互并播放歌曲,为了方便,我把要播放的歌曲定死了,大家可以灵活改进 MService: 复制代码代码如下: package com.tiantian.test;im ...