jQuery 源碼分析(二) 入口模塊

jQuery返回的對象本質上是一個JavaScript對象,而入口模塊則能夠保存對應的節點的引用,而後供其它模塊操做html

咱們建立jQuery對象時能夠給jQuery傳遞各類不一樣的選擇器,以下:node

  false        ;返回一個空jQuery對象jquery

  DOM節點      ;返回包含該DOM元素引用的jQuery對象。dom

  body        ;字符串'body',返回包含body元素引用的jQuery對象函數

  單獨標籤      ;調用document.createElement建立標籤對應的DOM元素源碼分析

  較複雜的html代碼  ;調用jQuery.buildFragment建立元素ui

  函數        ;是$(document).ready(function)的簡寫,等到DOM加載完畢後再執行,後面有幾篇專門介紹this

例如:spa

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
    <p id="p">123</p>
    <script> console.log( $(false) ) console.log( $(p) ) console.log( $('body') ) console.log( $('<p>123</p>') ) $(function(){console.log('Dom loaded')}) </script>
</body>
</html>

輸出以下:rest

輸出的五條信息分別對應上面的五個輸出,第一條爲空jQuery對象,第二條爲包含p元素的jQuery對象,第三條爲包含body節點引用的jQuery對象,第四條爲jQuery建立的未掛載到dom的jQuery對象,第五條就直接輸出信息的,對應着例子的$(function(){})對象

 

 源碼分析


 writer by:大沙漠 QQ:22969969

 入口模塊就是上一篇文章分析的jQuery內部的jQuery.fn.init函數,該函數會經過參數的不一樣來作不一樣的實現,以下:

init: function( selector, context, rootjQuery ) {           //負責解析參數selector和context的類型,並執行相應的邏輯
    var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined)
    if ( !selector ) {                                                        //selector是"",null,undefined和false的等能夠轉換爲false的狀況下,對應上面的第一個jQuery實例
      return this; } // Handle $(DOMElement)
    if ( selector.nodeType ) {                                                //selector有屬性nodeType,則認爲selector是DOM元素,例如:$(document.getELementById('d'))對應上面的第二個jQuery實例
      this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it
    if ( selector === "body" && !context && document.body ) {               //若是參數selector是字符串'body',且context爲空,如:$('body'),對應上面的第三個jQuery實例
      this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings
    if ( typeof selector === "string" ) {                                   //參數selector是字符串形式
      // Are we dealing with HTML string or an ID?
      if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {       //若是參數selector以"<"開頭、以">"結尾,且長度大於等於3
        // Assume that strings that start and end with <> are HTML and skip the regex check 
        match = [ null, selector, null ];                                                                                     //則假設這個字符串是HTML片斷,跳過正則quickExpr的檢查。注意這裏僅僅是假設,並不必定表示它是真正合法的HTML代碼
 } else { match = quickExpr.exec( selector );                                                                               //不然用quickExpr來檢測參數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 ) {                                                      //若是參數selector是單獨標籤好比$('<p></p>');
            if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } 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 {                                                            //參數selector是"#id"格式,如:$('#p1')
          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, $(...))
      } else if ( !context || context.jquery ) { 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 ) ) {                           //若是參數selector是函數,則認爲是綁定ready事件,從這裏能夠看出$(function) 是$(document).ready(function)的簡寫,這裏對應上面的第五個jQuery實例
      return rootjQuery.ready( selector ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); },

這樣jQuery實例就獲取到了對應的DOM節點的引用,以後就能夠用底層模塊或功能模塊進行操做了。

相關文章
相關標籤/搜索