接着上一篇随笔讨论。

如果selector是其他字符串情况就比较多了比较复杂了

// Handle HTML strings

if ( typeof selector === "string" ) {...} 

开始分不同的情况处理

// Are we dealing with HTML string or an ID?

if ( selector.charAt(0) === "<" && selector.charAt( 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 = quickExpr.exec( selector );

}

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 ]的形式,下面在代码中证明:

<!doctype html>

<html>

   <head>

      <title></title>

        <script src='jquery-1.7.1.js'></script>

   </head>

   <body>

       <div id=’div’></div>  

   </body>

   <script>

       $('<div>');

   </script>

</html>

在html里面我们创建一个jQuery对象然后再init方法里面输出得到的match结果:

if ( selector.charAt(0) === "<" && selector.charAt( 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 = quickExpr.exec( selector );

}

  console.log(match); // [null, "<div>", null];

下面我们修改一下参数改为$(‘#div’)然后再看一下结果

["#div", undefined, "div", index: 0, input: "#div"]

还有一种比较特殊的情况$(‘<div>123’)然后我们再看一下结果

["<div>dewrwe", "<div>", undefined, index: 0, input: "<div>dewrwe"]

我们可以看到id总是在第三个元素而标签值在第二个元素保存着,对于最后一种情况而言跟$(‘<div>’)是没有什么区别的因为生成dom元素时是不会处理第一个元素的。基于这个结果可以接着来分析下一个判断了。

接下来的会根据match的结果分为三种情况

if ( match && (match[1] || !context) ) {

          ...

} else if ( !context || context.jquery ) {

       ...

} else {

    ...

}

第一种情况满足的条件是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 = context instanceof jQuery ? context[0] : context;

doc = ( context ? context.ownerDocument || context : document );

// If a single string is passed in and it's a single tag

// just do a createElement and skip the rest

ret = rsingleTag.exec( selector );

if ( ret ) {

if ( jQuery.isPlainObject( context ) ) {

selector = [ document.createElement( ret[1] ) ];

jQuery.fn.attr.call( selector, context, true );

} else {

selector = [ doc.createElement( ret[1] ) ];

}

} else {

ret = jQuery.buildFragment( [ match[1] ], [ doc ] );

selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;

}

return jQuery.merge( this, selector);

首先修正一下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的情况

elem = document.getElementById( match[2] );

// Check parentNode to catch when Blackberry 4.6 returns

// nodes that are no longer in the document #6963

if ( elem && elem.parentNode ) {

// Handle the case where IE and Opera return items

// by name instead of ID

if ( elem.id !== match[2] ) {

return rootjQuery.find( selector );

}

// Otherwise, we inject the element directly into the jQuery object

this.length = 1;

this[0] = elem;

}

this.context = document;

this.selector = selector;

return this;

很简单直接调用原生js的id选择器但是有一些系统会出现bug

注释说的很清楚黑莓系统,就是元素已经不存在了但是依然能够匹配得到所以再加上父节点,不存在的元素肯定没有父节点的。还有一种情况就是ie和opera浏览器会出现按name值匹配的情况所以在做了一个判断

if ( elem.id !== match[2] ) {

如果真的不幸出现了那就不能使用原生方法而是用find方法也就是使用sizzle引擎了,在大多数正常情况下就直接将获取到的元素放到this里面就可以啦然后修改下context的值。Ok终于把第一个大分支分析完了。然后再看根据match的第二个分支

 else if ( !context || context.jquery ) {

   return ( context || rootjQuery ).find( selector );

}

这里是如果没有上下文或者上下文是jquery对象的时候这个比较简单就是直接用find方法了rootjQuery 就是$(document)

最后字符串的情况上面都不属于的话

return this.constructor( context ).find( selector );

This.constructor就是jQuery其实还是使用find方法。

jQuery构造函数init参数分析(二)的更多相关文章

  1. jQuery构造函数init参数分析(三)

    分析完了字符串情况剩下的就不多了. 5.参数selector是函数 这个就是很容易想到了,首先说一下dom加载.我们通常在head里面写脚本的时候需要等待文档加载在进行处理,js是这么写的 windo ...

  2. jQuery构造函数init参数分析(一)

    在我的上一篇随笔里面分析了jQuery的构造函数,jQuery对象中有一个原型方法init才是是真正的构造函数,通过init的原型对象跟jQuery的原型对象保持引用关系使得init的实例可以正常调用 ...

  3. 浅谈jQuery构造函数

    $()函数到底做的什么 jQuery在前端领域路人皆知,对于一向喜欢玩js的博主来说,虽然能力有限,但是还是很喜欢研究他的做为.那么一个简单的美元符号$与一对常见的()括号,jQuery底层到底做了哪 ...

  4. jQuery学习笔记之jQuery.fn.init()的参数分析

    这篇文章主要介绍了jQuery.fn.init()的参数分析,需要的朋友可以参考下   从return new jQuery.fn.init( selector, context, rootjQuer ...

  5. jQuery分析(3) - jQuery.fn.init

    1.前言 上一篇jQuery分析(2)中了解了jQuery库的骨架实现原理,这就好比摇滚音乐,摇滚音乐不是某种音乐他就像一个音乐盒子,里面包含了各种不同的摇滚风格(山地.朋克.乡村.流行.硬摇.金属. ...

  6. 四.jQuery源码解析之jQuery.fn.init()的参数解析

    从return new jQuery.fn.init( selector, context, rootjQuery )中可以看出 参数selector和context是来自我们在调用jQuery方法时 ...

  7. jquery源码分析(二)——架构设计

    要学习一个库首先的理清它整体架构: 1.jQuery源码大致架构如下:(基于 jQuery 1.11 版本,共计8829行源码)(21,94)                定义了一些变量和函数jQu ...

  8. jQuery 源码分析(二) 入口模块

    jQuery返回的对象本质上是一个JavaScript对象,而入口模块则可以保存对应的节点的引用,然后供其它模块操作 我们创建jQuery对象时可以给jQuery传递各种不同的选择器,如下: fals ...

  9. jQuery构造函数分析

    在我的上一篇文章里面 阐述了jQuery的大致框架,知道了所有代码都是写在了一个自调用匿名函数里面,并且传入了window对象,源码是这样的: (function( window, undefined ...

随机推荐

  1. AIX下如何根据端口号查找相应的进程

    1. $ netstat -Aan |grep 8080 f1000e0002321bb8 tcp 0 0 *.8080 *.* LISTEN 2. $ rmsock f1000e0002321bb8 ...

  2. nodejs在Liunx上的部署生产方式-PM2

    先安装:npm install -g pm2 (注意:使用它要先安装它,用root账号和全局模式安装一下) 安装完成使用:pm2 -v 查看版本信息 安装成功之后,启动nodejs项目:pm2 sta ...

  3. Win7搭建NodeJs开发环境以及HelloWorld展示—图解

    Windows 7系统下搭建NodeJs开发环境(NodeJs+WebStrom)以及Hello World!展示,大体思路如下:第一步:安装NodeJs运行环境.第二步:安装WebStrom开发工具 ...

  4. TFS简介

    Team Foundation Server(TFS)是一种为 Microsoft 产品提供 源代码管理.数据收集.报告和项目跟踪,而为协作软件开发的项目.可作为独立的软件,或 Visual Stud ...

  5. java io系列16之 PrintStream(打印输出流)详解

    本章介绍PrintStream以及 它与DataOutputStream的区别.我们先对PrintStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:htt ...

  6. redis学习之二from github

    大概敲了一遍基本命令,熟悉了redis的存储方式.现在开始进一步系统的学习.学习教程目前计划有三个,一个是github上的https://github.com/JasonLai256/the-litt ...

  7. MFC抓网页

    CString chinachar_str("读取的东西:"); CInternetSession sion(NULL,); CHttpFile *http=NULL; CStri ...

  8. .net using使用小结

    在.net中using使用方法有3种,分别是using指令.using定义使用范围.using别名. using指令,即引用命名空间. using System; using System.Colle ...

  9. IE条件注释详解

    IE条件注释是微软从IE5开始就提供的一种非标准逻辑语句,作用是可以灵活的为不同IE版本浏览器导入不同html元素,如:样式表,html标签等.很显然这种方法的最大好处就在于属于微软官方给出的兼容解决 ...

  10. 输入URL之后都发生了什么

    输入URL之后都发生了什么 这个标题印象中已经有很多讨论了.也来说说这个话题. 从头开始,当你的电脑使用网线连接到网络的时候,我们都知道,这个时候你的电脑会获取一个IP,这个IP就是你的唯一标识了.好 ...