看了一下午还是有很多地方没弄明白,jQuery的一些工具方法的原理也不完全清楚,这篇文章会随着我深入阅读jQuery源码的同时不断更新。
// Initialize a jQuery object // 初始化Jquery对象 // A central reference to the root jQuery(document) var rootjQuery, // Use the correct document accordingly with window argument (sandbox) document = window.document, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // 检测html字符串的正则表达式 rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/, init = jQuery.fn.init = function( selector, context ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Handle HTML strings // 下面的match中,match[0]存放原字符串,match[1]存html标签,match[2]存#q中的“q” 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 //selector是HTML标签,类似<div>123</div> match = [ null, selector, null ]; } else { //不是html标签 match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id // 匹配的html或确保没有上下文指定为# id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) // 1.处理html标签 if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; // scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present //jQuery.merge( first, second ) 合并两个数组内容到第一个数组 //jQuery.parseHTML()函数用于将HTML字符串解析为对应的DOM节点数组 //对于HTML文档来说,documentElement是<html>标签对应的Element对象,ownerDocument是document对象 jQuery.merge( this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) // rsingleTag匹配匹配独立标签,比如'<html></html>'或者'<div></div>' if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) //2.处理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 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, $(...)) //3.处理表达式 } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) //4.处理有上下文的表达式 } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) //5.处理DOM元素 } else if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready //6.处理函数 } else if ( jQuery.isFunction( selector ) ) { return typeof rootjQuery.ready !== "undefined" ? rootjQuery.ready( selector ) : // Execute immediately if ready is not present selector( jQuery ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); };