jQuery源代码学习笔记:jQuery.fn.init(selector,context,rootjQuery)代码具体解释

3.1 源代码

init: function( selector, context, rootjQuery ) {
		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
        //假设selector为空格。!selector为false
		if (!selector) {
            //此时this为空jQuery对象
			return this;
		}

		// Handle $(DOMElement)
        //nodeType节点类型。利用是否有nodeType属性来推断是否是DOM元素
		if ( selector.nodeType ) {
            //将第一个元素和属性context指向selector
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

		// The body element only exists once, optimize finding it
        //由于body仅仅出现一次。利用!context进行优化
		if ( selector === "body" && !context && document.body ) {
            //context指向document对象
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
		    // Are we dealing with HTML string or an ID?

//以<开头以>结尾,且长度大于等于3。这里假设是HTML片段,跳过queckExpr正则检查
			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 );
			}

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					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) {
                        //假设context是普通对象
					    if (jQuery.isPlainObject(context)) {
                            //之所以放在数组中。是方便后面的jQuery.merge()方法调用
						    selector = [document.createElement(ret[1])];
                            //调用attr方法。传入參数context
							jQuery.fn.attr.call( selector, context, true );

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

                    //复杂HTML的处理方法
					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
					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

					    //即使是documen.getElementById这样核心的方法也要考虑到浏览器兼容问题,可能找到的是name而不是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;
				}

			// HANDLE: $(expr, $(...))
            //没有指定上下文,运行rootjQuery.find()。制定了上下文且上下文是jQuery对象,运行context.find()
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)

            //假设指定了上下文。且上下文不是jQuery对象
			} else {
                //先创建一个包括context的jQuery对象。然后调用find方法
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}
        //selector是jquery对象
		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}
        //合并到当前jQuery对象
		return jQuery.makeArray( selector, this );
	},

当中里面调用的其它jQuery函数待后面再具体学习。

1、当中用到了两个正則表達式:

(1)quickExpr = /^(?

:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;

解释:?:是非捕获组的意思。非捕获组仅仅參与匹配。但不会把匹配到的内容捕获到组里,减少了内存的占用。

[^#<]*匹配除#<以外的随意字符,且出现0次或多次

(<[\w\W]+>):

\w表示匹配字母数字、下划线,\W正好相反,这里匹配的是以字母数字下划线作为第一个字母的一个标签,比方<div>

[^>]*匹配除>之外的全部字符,且出现0次或多次,$结束,表示结束时不能为>字符

#(\w\-]*)$  #id的匹配。id仅仅能为字母、数字、下划线和减号

(2)rsingleTag = /^<(\w+)\s*\/?

>(?:<\/\1>)?$/;

解释:^<(\w+)\s*\/?

>:

^<:以<开头

(\w+):匹配的字母、数字、下划线

\s*:匹配空格符0次或多次,比方能够匹配<div  >这种

\/?>:匹配/符号0次或1次。比方匹配<img    />这种

(?:<\/\1>):\1表示的是前面的(),这里指的就是(\w+),比方前面是<div>。这里就要是</div>

最后的?$表示的是此元素为截止符,要么截止在</div>,要么没有就是前面的<img >或者是<img />

到此就把全部的单独的标签的情况考虑全然了。

学以致用

<script type="text/javascript">
        var quickExpr = /^(?

:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
        var rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/;

        var match = quickExpr.exec("abc<div>#id");
        if (match) {
            alert(RegExp.$1)
        }

        var match1 = rsingleTag.exec("<div></div>");
        if (match1) {
            alert(RegExp.$1);
        }
    </script>
时间: 2024-12-17 13:40:24

jQuery源代码学习笔记:jQuery.fn.init(selector,context,rootjQuery)代码具体解释的相关文章

jQuery源代码学习之六——jQuery数据缓存Data

一.jQuery数据缓存基本原理 jQuery数据缓存就两个全局Data对象,data_user以及data_priv; 这两个对象分别用于缓存用户自定义数据和内部数据: 以data_user为例,所有用户自定义数据都被保存在这个对象的cache属性下,cache在此姑且称之为自定义数据缓存: 自定义数据缓存和DOM元素/javascript对象通过id建立关联,id的查找通过DOM元素/javascript元素下挂载的expando属性获得 话不多说,直接上代码.相关思路在代码注释中都有讲解

jQuery源代码学习之五——jQuery.when

jQuery.when提供了基于一个或多个对象的状态来执行回调函数的功能,通常是基于具有异步事件的异步队列. 如果传入多个异步队列,jQuery.when会返回一个新的主异步队列的只读副本(promise),这个副本将跟踪所传递的异步队列的最终状态. 当所有异步队列都成功,主异步队列的成功回调函数将会被调用,参数是包含所有异步队列成功参数的数组:为了达到这一效果,方法jQuery.when会维护一个计数器,并在每个异步队列上 如果其中一个异步队列变成失败状态,主异步队列的失败回调函数将被调用,参

jQuery源代码阅读之一——jQuery总体结构及jQuery构造函数

一.jQuery总体架构 jQuery作为一款强大的js库,由以下模块构成: (function(window,undefined){ var jQuery=function(selector,context){ //... }; //工具方法utilities //回调函数 callbacks //异步队列 Defered Object //浏览器功能测试 Support //数据缓存 Data //队列 Queue //属性操作 Attributes //事件系统 Events //选择器

jQuery来源学习笔记:扩展的实用功能

// 扩展的实用功能 jQuery.extend({ // http://www.w3school.com.cn/jquery/core_noconflict.asp // 释放$的 jQuery 控制权 // 很多 JavaScript 库使用 $ 作为函数或变量名,jQuery 也一样. // 在 jQuery 中,$ 仅仅是 jQuery 的别名,因此即使不使用 $ 也能保证全部功能性. // 假如我们须要使用 jQuery 之外的还有一 JavaScript 库,我们能够通过调用 $.n

jquery.extend 学习笔记

//// jquery.extend 学习笔记// jquery.extend 扩展方法设计的很巧妙,动态增加静态方法和属性 // 虽然网上资料很多,还是跟据自已的学习理解记录一下.// //定义一个Person构造函数function Person(iname,iage){ this.uname = iname; this.age = iage;} //定义原型方法Person.prototype = { showN:function(){ //调用静态方法 Person.showName(t

jQuery插件学习笔记

最近在研究jQuery插件,插件编写的目的是给已经有的一系列方法或函数做一个封装,以便在其他地方重复使用,方便后期维护. JQuery除了提供一个简单.有效的方式进行管理元素以及脚本,它还还提供了例外一种机制:即给核心模块增加自己的方法和额外的功能.通过这种机制,Jquery允许我们自己创建属于我们自己的插件,提高我们在开发过程中的效率. 虽然在jQuery命名空间中,我们禁止使用了大量的javaScript函数名和变量名.但是仍然不可避免某些函数或变量名将于其他jQuery插件冲突,因此我们习

JavaScript学习笔记——jquery中html()、text()、val()的区别

.html()用为读取和修改元素的HTML标签 .text()用来读取或修改元素的纯文本内容 .val()用来读取或修改表单元素的value值. 这三个方法功能上的对比 .html(),.text(),.val()三种方法都是用来读取选定元素的内容:只不过.html()是用来读取元素的HTML内容(包括其Html标签),.text()用来读取元素的纯文本内容,包括其后代元素,.val()是用来读取表单元素的"value"值.其中.和.text()方法不能使用在表单元素上,而.val()

jQuery学习笔记——jQuery基础核心

代码风格 在jQuery程序中,不管是页面元素的选择.内置的功能函数,都是美元符号“$”来起始的.而这个“$”就是jQuery当中最重要且独有的对象:jQuery对象,所以我们在页面元素选择或执行功能函数的时候可以这么写: $(function () {}); //执行一个匿名函数 $(‘#box’);//进行执行的ID元素选择 $(‘#box’).css(‘color’, ‘red’);//执行功能函数由于$本身就是jQuery对象的缩写形式,那么也就是说上面的三段代码也可以写成如下形式:jQ

jQuery学习笔记——jQuery常规选择器

一.简单选择器在使用 jQuery 选择器时,我们首先必须使用“$()”函数来包装我们的 CSS 规则.而CSS 规则作为参数传递到 jQuery 对象内部后,再返回包含页面中对应元素的 jQuery 对象.随后,我们就可以对这个获取到的 DOM 节点进行行为操作了.#box {//使用 ID 选择器的 CSS 规则color:red;//将 ID 为 box 的元素字体颜色变红}在 jQuery 选择器里,我们使用如下的方式获取同样的结果:$('#box').css('color', 'red