jQuery源码解析之init

阅读更多
以下是对jquery-1.6.1.js中的init的解析,旨在分析ID选择器返回唯一一个匹配的元素(1),而多条件选择器返回的确是全部匹配的元素(2)。
(1)是ID选择器走的分支
(2)是多条件选择器走的分支

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

		// 传入的selector为$(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

		// 传入的selector是Dom元素,如document.getElementById("id")
        //注解1
		if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

		if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// 传入""
			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		
                    ret = rsingleTag.exec( selector ); // "" to "tr"		
					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true ); //TODO

						} else {
							selector = [ doc.createElement( ret[1] ) ]; //createElement: "tr" --> ""
						}

					} else {
					    //传入的selector中不包括Element,例如"fff"
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; //return NodeList[]
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
                    //(1)是ID选择器走的分支
					elem = document.getElementById( match[2] );

					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
                        //(1)是ID选择器走的分支
						this.length = 1;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
                //(2)是多条件选择器走的分支
				return (context || rootjQuery).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if (selector.selector !== undefined) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	}




ID选择器和多条件选择器Demo:
$("#id");
$("#id1, #id2");

上面的例子在调用init创建就Query对象的时候,根本没有传递context,这里借用http://api.jquery.com/context/中的一句话来解释一下:The value of this property is typically equal to document, as this is the default context for jQuery objects if none is supplied. The context may differ if, for example, the object was created by searching within an