您的位置:首页 > Web前端 > JQuery

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

2014-12-23 15:17 351 查看

总体架构

  首先我们来看下在家在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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: