首页 > 代码库 > jQuery技术内幕之总体架构与初始化函数

jQuery技术内幕之总体架构与初始化函数

总体架构

  首先我们来看下在家在jquery的时候发生了什么,jquery的源码最外层的结构为:

(function( global, factory ) {    if ( typeof module === "object" && typeof module.exports === "object" ) {        ...      } else {        factory( global );    }}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {    var jQuery;    var strundefined = typeof undefined;    ...    if ( typeof noGlobal === strundefined ) {      window.jQuery = window.$ = jQuery;    }}));

构造jquery对象

  接下来看工厂方法是如何创建jquery对象的

function( window, noGlobal ) {    ......    var jQuery = function( selector, context ) {        return new jQuery.fn.init( selector, context );    };    jQuery.fn = jQuery.prototype = {        ......    };    jQuery.extend = jQuery.fn.extend = function() {        ......    };    ......    var init = jQuery.fn.init = function( selector, context ) {};    init.prototype = jQuery.fn;    ......    if ( typeof noGlobal === strundefined ) {        window.jQuery = window.$ = jQuery;    }    return jQuery;}

  下面我们再来看window对象的jQuery构造函数是如何创建jQuery实例的

var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;init = jQuery.fn.init = function( selector, context ){        var match, elem;        if ( !selector ) {            return this;        }        if ( typeof selector === "string" ) {            if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {                match = [ null, selector, null ];            } else {                match = rquickExpr.exec( selector );            }            if ( match && (match[1] || !context) ) {                if ( match[1] ) {                    context = context instanceof jQuery ? context[0] : context;                    jQuery.merge( this, jQuery.parseHTML(                        match[1],                        context && context.nodeType ? context.ownerDocument || context : document,                        true                    ) );                    if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {                        for ( match in context ) {                            if ( jQuery.isFunction( this[ match ] ) ) {                                this[ match ]( context[ match ] );                            } else {                                this.attr( match, context[ match ] );                            }                        }                    }                    return this;                } else {                    elem = document.getElementById( match[2] );                    if ( elem && elem.parentNode ) {                        this.length = 1;                        this[0] = elem;                    }                    this.context = document;                    this.selector = selector;                    return this;                }            } else if ( !context || context.jquery ) {                return ( context || rootjQuery ).find( selector );            } else {                return this.constructor( context ).find( selector );            }        } else if ( selector.nodeType ) {            this.context = this[0] = selector;            this.length = 1;            return this;        } else if ( jQuery.isFunction( selector ) ) {            return typeof rootjQuery.ready !== "undefined" ?                rootjQuery.ready( selector ) :                selector( jQuery );        }        if ( selector.selector !== undefined ) {            this.selector = selector.selector;            this.context = selector.context;        }        return jQuery.makeArray( selector, this );}
var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);jQuery.parseHTML = function( data, context, keepScripts ) {    if ( !data || typeof data !== "string" ) {        return null;    }    if ( typeof context === "boolean" ) {        keepScripts = context;        context = false;    }    context = context || document;    var parsed = rsingleTag.exec( data ),        scripts = !keepScripts && [];    if ( parsed ) {        return [ context.createElement( parsed[1] ) ];    }    parsed = jQuery.buildFragment( [ data ], context, scripts );    if ( scripts && scripts.length ) {        jQuery( scripts ).remove();    }    return jQuery.merge( [], parsed.childNodes );};
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;var rhtml = /<|&#?\w+;/;var rtagName = /<([\w:]+)/;var rscriptType = /^$|\/(?:java|ecma)script/i;var wrapMap = {    option: [ 1, "<select multiple=‘multiple‘>", "</select>" ],    thead: [ 1, "<table>", "</table>" ],    col: [ 2, "<table><colgroup>", "</colgroup></table>" ],    tr: [ 2, "<table><tbody>", "</tbody></table>" ],    td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],    _default: [ 0, "", "" ]};buildFragment: function( elems, context, scripts, selection ) {        var elem, tmp, tag, wrap, contains, j,            fragment = context.createDocumentFragment(),            nodes = [],            i = 0,            l = elems.length;        for ( ; i < l; i++ ) {            elem = elems[ i ];            if ( elem || elem === 0 ) {                if ( jQuery.type( elem ) === "object" ) {                    jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );                } else if ( !rhtml.test( elem ) ) {                    nodes.push( context.createTextNode( elem ) );                } else {                    tmp = tmp || fragment.appendChild( context.createElement("div") );                    tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();                    wrap = wrapMap[ tag ] || wrapMap._default;                    tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];                    j = wrap[ 0 ];                    while ( j-- ) {                        tmp = tmp.lastChild;                    }                    jQuery.merge( nodes, tmp.childNodes );                    tmp = fragment.firstChild;                    tmp.textContent = "";                }            }        }        fragment.textContent = "";        i = 0;        while ( (elem = nodes[ i++ ]) ) {            if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {                continue;            }            contains = jQuery.contains( elem.ownerDocument, elem );            tmp = getAll( fragment.appendChild( elem ), "script" );            if ( contains ) {                setGlobalEval( tmp );            }            if ( scripts ) {                j = 0;                while ( (elem = tmp[ j++ ]) ) {                    if ( rscriptType.test( elem.type || "" ) ) {                        scripts.push( elem );                    }                }            }        }        return fragment;}
(function( window ) {    var setDocument,          docElem,          preferredDoc = window.document,          rnative = /^[^{]+\{\s*\[native \w/;    function Sizzle( selector, context, results, seed ){        ......    }    setDocument = Sizzle.setDocument = function( node ) {        var hasCompare,              doc = node ? node.ownerDocument || node : preferredDoc;        hasCompare = rnative.test( docElem.compareDocumentPosition );      contains = hasCompare || rnative.test( docElem.contains ) ?        function( a, b ) {            var adown = a.nodeType === 9 ? a.documentElement : a,                bup = b && b.parentNode;            return a === bup || !!( bup && bup.nodeType === 1 && (                adown.contains ?                    adown.contains( bup ) :                    a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16            ));        } :        function( a, b ) {            if ( b ) {                while ( (b = b.parentNode) ) {                    if ( b === a ) {                        return true;                    }                }            }            return false;        };    }    setDocument();    ......})(window)  

jQuery技术内幕之总体架构与初始化函数