时间:2021-05-26
如果selector是其他字符串情况就比较多了比较复杂了
// Handle HTML stringsif ( typeof selector === "string" ) {...}开始分不同的情况处理
If里面先判断第一个字符是“<”最后一个字符是“>”并且长度大于3就假设此时的selector是html简单标签 ,比如$(‘<div>')但是记住仅仅是假设”assume”比如$(‘<sdfadfadf>')这样的也会走这里。然后把match数组修改成[null,selector,null],这里的match是在init函数里面声明的变量,主要是用来作为区分是参数类型的工具稍后在将可能情况列出,下面是源码中声明的四个变量
init: function( selector, context, rootjQuery ) {var match, elem, ret, doc;如果不满足if的条件就会调用一个正则去得到match的结果,quickExpr是jQuery构造函数里面声明的变量
// A simple way to check for HTML strings or ID strings// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,这个正则主要是为了区别html字符串和id字符串的,第二个注释中讲到了为了避免基于 location.hash的 XSS 攻击,于是在 quickExpr 中增加了 #(#9521)的意思是我们可以在jQuery官网找到相关解释。
首先访问http://bugs.jquery.com/然后搜索对应的值即可
quickExpr.exec( selector )执行的结果可以是一个数组,数组的第一个元素是匹配的元素,剩下的分别是分组匹配的元素,这个正则有两个分组(<[\w\W]+>)[^>]和([\w\-]*)一个是标签一个是id值。最终会把结果交给match。下面就来分析下match的各种情况首先单标签不用正则式是 [ null, selector, null ]的形式,下面在代码中证明:
在html里面我们创建一个jQuery对象然后再init方法里面输出得到的match结果:
下面我们修改一下参数改为$(‘#div')然后再看一下结果
复制代码 代码如下:
["#div", undefined, "div", index: 0, input: "#div"]
还有一种比较特殊的情况$(‘<div>123')然后我们再看一下结果
复制代码 代码如下:
["<div>dewrwe", "<div>", undefined, index: 0, input: "<div>dewrwe"]
我们可以看到id总是在第三个元素而标签值在第二个元素保存着,对于最后一种情况而言跟$(‘<div>')是没有什么区别的因为生成dom元素时是不会处理第一个元素的。基于这个结果可以接着来分析下一个判断了。
接下来的会根据match的结果分为三种情况
第一种情况满足的条件是match一定要有值,match[1]就是第二个元素就是保存标签的这个有值或者不存在上下文,但是好像没有id什么事啊?其实不是的通过分析match的结果可以知道第二个元素没有值肯定就是id选择器得到的结果,而id是唯一的,不需要写上下文(其实写了上下文也会正常执行只不过会使用Sizzle而不是在这里处理了跟body是一样的)。好了第一个条件进来的情况就是
1.标签
$(‘<div>') $(‘<div>123') $(‘<div>23213213</div>')...
2.没有上下文的id $(‘#div')
第一个条件内部又进行了细分:
// HANDLE: $(html) -> $(array)if ( match[1] ) { ...// HANDLE: $("#id")}else{}很显然if是处理标签的else是处理id的,先来看看是怎么处理标签的吧
首先修正一下context的值,如果是jQuery对象就把他变成dom元素就是使用下标的方法这个原理之前说过了,然后有处理了doc变量,如果context不存在就把document赋值给doc如果存在且有ownerDocument属性那就是dom元素了这个值还是document如果不是dom元素比如普通的js对象的话那就把这个对象赋值给doc变量。紧接着对selector又进行了一个正则判断,这个正则也是在jQuery构造函数里面声明的目的是判断单标签 比如<div>这样的
复制代码 代码如下:
// Match a standalone tag
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
然后把结果交给ret变量,基于ret的值又进行划分按照单标签和复杂标签分开处理ret值存在那就是匹配到了单标签然后再根据context是不是普通对象又分为两种情况isPlainObject是检测是不是普通对象的方法,如果是普通对象,就利用js原生方法createElement传入标签创建元素并放在一个数组里面,之所以这样是为了以后跟jquery对象合并方便,然后把数组赋值给selector,后采用对象冒充的方法调用attr方法,这里attr居然有3个参数,而平常我们使用的api里面是两个参数,其实jQuery中有很多类似的情况,同样的方法有着对内对外两个接口。第二个参数就是对象形式的上下文,因为attr可以像
复制代码 代码如下:
$("img").attr({ src: "test.jpg", alt: "Test Image" });
这给我们的其实就是我们以后可以$(‘<div>',{id:'div'})这样写了也是支持的。如果不是对象就直接创建元素不考虑属性。还是把创建的元素放在数组里面。如果ret没有值那就是复杂的标签了比如$(‘<div>231</div>')这样的这个时候原生的js就搞不定啦需要调取另外一个方法jQuery.buildFragment来处理,这个方法实现以后在学习吧,总之最后都会创建dom元素。最后返回合并后的结果
复制代码 代码如下:
return jQuery.merge( this, selector );
不像之前的return this这里是返回merge执行后的结果其实他的任务就是把放在数组里面的创建好的的dom元素合并到jquery元素中去,最终变成{0:div,length:1...}这样的对象形式。这样的话简标签情况就处理完毕。
然后else里面处理的是id的情况
很简单直接调用原生js的id选择器但是有一些系统会出现bug
注释说的很清楚黑莓系统,就是元素已经不存在了但是依然能够匹配得到所以再加上父节点,不存在的元素肯定没有父节点的。还有一种情况就是ie和opera浏览器会出现按name值匹配的情况所以在做了一个判断
if ( elem.id !== match[2] ) {
如果真的不幸出现了那就不能使用原生方法而是用find方法也就是使用sizzle引擎了,在大多数正常情况下就直接将获取到的元素放到this里面就可以啦然后修改下context的值。Ok终于把第一个大分支分析完了。然后再看根据match的第二个分支
这里是如果没有上下文或者上下文是jquery对象的时候这个比较简单就是直接用find方法了rootjQuery 就是$(document)
最后字符串的情况上面都不属于的话
复制代码 代码如下:
return this.constructor( context ).find( selector );
This.constructor就是jQuery其实还是使用find方法。
以上所述就是本文的全部内容了,希望大家能够喜欢。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
在我的上一篇随笔里面分析了jQuery的构造函数,jQuery对象中有一个原型方法init才是是真正的构造函数,通过init的原型对象跟jQuery的原型对象保
init构造器由于这个函数直接和jQuery()的参数有关,先来说下能接受什么样的参数。源码中接受3个参数:init:function(selector,con
一、源码思路分析总结概要:jQuery的核心思想可以简单概括为“查询和操作dom”,今天主要是分析一下jQuery.prototype.init选择器构造函数,
promise基本用法Promise对象是一个构造函数,用来生成Promise实例。Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resol
本节引言:1.子类作用与构造方法参数分析:1)CornerPathEffectCornerPathEffect(floatradius)2)DashPathEf