萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> jQuery構造函數init參數分析續

jQuery構造函數init參數分析續

   其實樓主的F和jQuery.fn.init是相等的; 實現功能是和jq一樣的, 只是jq的把構造函數放進原型;如果非要說原因,個人理解jq這樣寫整體結構清晰,先是入口構造函數,緊跟著是原型部分(原型裡面init是初始化),但是不好理解;乍一看確實挺繞, 我也是看了好久才明白怎麼回事

  如果selector是其他字符串情況就比較多了比較復雜了

  ?

1 2 // Handle HTML strings if ( typeof selector === "string" ) {...}

  開始分不同的情況處理

  ?

1 2 3 4 5 6 7 // 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簡單標簽 ,比如$(‘

')但是記住僅僅是假設”assume”比如$(‘')這樣的也會走這裡。然後把match數組修改成[null,selector,null],這裡的match是在init函數裡面聲明的變量,主要是用來作為區分是參數類型的工具稍後在將可能情況列出,下面是源碼中聲明的四個變量

 

  ?

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

  如果不滿足if的條件就會調用一個正則去得到match的結果,quickExpr是jQuery構造函數裡面聲明的變量

  ?

1 2 3 // A simple way to check for HTML strings or ID strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[wW]+>)[^>]*$|#([w-]*)$)/,

  這個正則主要是為了區別html字符串和id字符串的,第二個注釋中講到了為了避免基於 location.hash的 XSS 攻擊,於是在 quickExpr 中增加了 #(#9521)的意思是我們可以在jQuery官網找到相關解釋。

  首先訪問http://bugs.jquery.com/然後搜索對應的值即可

  quickExpr.exec( selector )執行的結果可以是一個數組,數組的第一個元素是匹配的元素,剩下的分別是分組匹配的元素,這個正則有兩個分組(<[wW]+>)[^>]和([w-]*)一個是標簽一個是id值。最終會把結果交給match。下面就來分析下match的各種情況首先單標簽不用正則式是 [ null, selector, null ]的形式,下面在代碼中證明:

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 <!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結果:

  ?

1 2 3 4 5 6 7 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"]

  還有一種比較特殊的情況$(‘

123')然後我們再看一下結果

 

  代碼如下:

  ["

dewrwe", " ", undefined, index: 0, input: " dewrwe"]

 

  我們可以看到id總是在第三個元素而標簽值在第二個元素保存著,對於最後一種情況而言跟$(‘

')是沒有什麼區別的因為生成dom元素時是不會處理第一個元素的。基於這個結果可以接著來分析下一個判斷了。

 

  接下來的會根據match的結果分為三種情況

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 if ( match && (match[1] || !context) ) {   ...   } else if ( !context || context.jquery ) {   ...   } else {   ...   }

  第一種情況滿足的條件是match一定要有值,match[1]就是第二個元素就是保存標簽的這個有值或者不存在上下文,但是好像沒有id什麼事啊?其實不是的通過分析match的結果可以知道第二個元素沒有值肯定就是id選擇器得到的結果,而id是唯一的,不需要寫上下文(其實寫了上下文也會正常執行只不過會使用Sizzle而不是在這裡處理了跟body是一樣的)。好了第一個條件進來的情況就是

  1.標簽

  $(‘

') $(‘ 123') $(‘ 23213213 ')...

 

  2.沒有上下文的id $(‘#div')

  第一個條件內部又進行了細分:

  ?

1 2 3 4 5 6 7 8 9 10 // HANDLE: $(html) -> $(array) if ( match[1] ) {   ...   // HANDLE: $("#id")   }else{   }

  很顯然if是處理標簽的else是處理id的,先來看看是怎麼處理標簽的吧

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 ) {
copyright © 萬盛學電腦網 all rights reserved