jQuery選擇器能夠依照傳入數據的類型分爲五大類:html
下面咱們來看一下jQuery構造函數代碼(jQuery-2.2.2第2832行起)的架構:node
jQuery.fn.init = function(selector, context){ if(!selector){ // part1.處理$(null), $(undefined), $(false), $("") } if(typeof selector == "string"){ // part2.匹配selector並將結果傳入match中 } if(match && (match[1] || !context)){ // part3.建立標籤或按#id查詢 }else{ // part4.處理複雜選擇器 } } // 一些其餘的不常見狀況 else {...} return jQuery.makeArray(selector, this); }
能夠發現jQ將代碼依照selector的類型分爲了幾個部分。下面咱們來依次分析這幾部分的代碼。jquery
此段完整代碼以下:正則表達式
// HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; }
此段完整代碼以下:數組
if ( selector[ 0 ] === "<" &&selector[ 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 = rquickExpr.exec( selector ); }
// 匹配html標籤或#id rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
經過分析rquickExpr正則表達式,咱們能夠得出在selector分別爲如下幾種值時返回值match的結構:架構
1. selector = "<div>"函數
match = [null, "<div>", null]
2. selector = "<div>content</div>"ui
match = [null, "<div>content</div>", null]
3. selector = "<div></div>content"this
match = ["<div></div>content", "<div></div>", null]
4. selector = #idspa
match = [#id, null, #id]
此段完整代碼以下:
// 若是是html標籤 if ( match[ 1 ] ) { // 若是傳入的context是jQ對象,將其轉換成原生對象 context = context instanceof jQuery ? context[0] : context; // 將傳入的html字符串轉換成節點數組並傳入this中 jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true)); // 若是是$(html, props)的形式,則要設置對應屬性或執行方法 if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // 若 prop 的某一項是jQ方法 if (jQuery.isFunction(this[match])) { this[match](context[match]); // 不然設置對應屬性 } else { this.attr(match, context[match]); } } } return this; }
// 匹配單標籤 var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
關鍵位置的語意都已在註釋中講解過了,下面主要介紹一下$.parseHTML和$.merge這兩個方法在其中的應用:
jQuery.parseHTML( data [, context ] [, keepScripts ] )
jQuery.merge(first, second)
咱們常常用$.merge來進行數組的合併。在本例中須要強調的一點是,$.merge被用來將一個數組合併到類數組對象中。就像下面這樣:
var obj = {0: "hello", 1: "pansy", length: 2}; var arr = ["from", "arr"]; console.log($.merge(obj, arr)); // Object {0: "hello", 1: "pansy", 2: "from", 3: "arr", length: 4}
// HANDLE: $(#id) else { elem = document.getElementById( match[ 2 ] ); // Support: Blackberry 4.6 // gEBID returns nodes no longer in the document (#6963) if ( elem && elem.parentNode ) { // Inject the element directly into the jQuery object this.length = 1; this[ 0 ] = elem; } this.context = document; this.selector = selector; return this; }
// 處理形如$(".class"), $("ul li+p")等等 if ( !context || context.jquery ) { return ( context || root ).find( selector ); // 當傳入上下文是原生對象時,調用構造函數返回jQ對象 } else { return this.constructor( context ).find( selector ); }
此處複雜選擇器所有藉助$().find()方法實現,使用了sizzle引擎,咱們稍後再進行介紹。