jQuery1.2.1架构分析----初始化
当页面加载jQuery脚本后,jQuery就开始了自己的初始化过程:创建jQuery以及jQuery的构造和原型函数并等待调用。让我们分析一下这个过程: 1.首先,检查jQuery和$是否已定义(避免和其它javascript框架的冲突,这意味着为了避免冲突,你应该让其它的框架应早于jQuery加载),将其进行重命名为_jQuery和_$.并定义jQuery的别名为$。 看到这里,你应该明白,对于其它冲突的框架(主要是$的冲突),我们可以通过_$进行访问。 实际上,为了更加方便,jQuery还提供了一个noConflict方法,这个方法恢复了原有冲突的框架的_$为$,并返回jQuery方法以便于你重新命名。这样,对于jQuery框架,你使用jQuery代替$进行访问,对于其它框架,则通过$符号进行访问。 jQuery.noConflict=function(deep) { window.$ = _$; /*如果deep为true,jQuery也被替换了*/ if ( deep ) window.jQuery = _jQuery; return jQuery; } 让我们举个例子: <html> <head> <script src="prototype.js"></script> <script src="jquery.js"></script> <script> jQuery.noConflict(); // Use jQuery via jQuery(...) jQuery(document).ready(function(){ jQuery("div").hide(); }); // Use Prototype with $(...), etc. $('someid').style.display = 'none'; </script> </head> <body></body> </html> 更详细的说明你可以参阅http://docs.jquery.com/Using_jQuery_with_Other_Libraries,详细的说明了如何避免不同框架的冲突。 还是让我们看一下这个步骤的具体的代码: if ( typeof jQuery != "undefined" ) var _jQuery = jQuery; ... if ( typeof $ != "undefined" ) var _$ = $; window.$ = jQuery; 2.定义jQuery的构造和原型函数,这个过程同时定义了prototype的别名为fn:jQuery.prototype=jQuery.fn。jQuery的原型prototype在这里隆重的出场了,jQuery对象的原型prototype包括了诸多的核心方法和属性: init jquery 当前的版本号 size 返回了length属性 length get pushStack each ... 3.定义了evalScript函数 4.extend方法终于隆重登场了 5.定义了一个非常重要的属性名expando,如果后续的jQuery对象需要进行缓存,则对象会被赋予以该属性命名的属性,该属性的值为一个递增的uuid值(具体的内容可以参阅data方法)。 var expando = "jQuery" + (new Date()).getTime(); 6现在开使用extend方法来定义jQuery的诸多方法。 注意,不是定义jQuery对象的方法,因为这些方法只能通过诸如jQuery.noconflict()的形式调用。这些方法包括: noconflict isFunction isXMLDoc globalEval each map ... 6开始识别浏览器以及其特性 var userAgent = navigator.userAgent.toLowerCase(); jQuery.browser = { version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1], safari: /webkit/.test(userAgent), opera: /opera/.test(userAgent), msie: /msie/.test(userAgent) && !/opera/.test(userAgent), mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) }; var styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat"; jQuery.extend({ boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat", styleFloat: jQuery.browser.msie ? "styleFloat" : "cssFloat", props: { "for": "htmlFor", "class": "className", "float": styleFloat, cssFloat: styleFloat, styleFloat: styleFloat, innerHTML: "innerHTML", className: "className", value: "value", disabled: "disabled", checked: "checked", readonly: "readOnly", selected: "selected", maxlength: "maxLength" } }) 7.通过each方法,非常灵巧简化的实现了诸多方法: jQuery.each({ parent: "a.parentNode", parents: "jQuery.dir(a,'parentNode')", next: "jQuery.nth(a,2,'nextSibling')", prev: "jQuery.nth(a,2,'previousSibling')", nextAll: "jQuery.dir(a,'nextSibling')", prevAll: "jQuery.dir(a,'previousSibling')", siblings: "jQuery.sibling(a.parentNode.firstChild,a)", children: "jQuery.sibling(a.firstChild)", contents: "jQuery.nodeName(a,'iframe')?a.contentDocument||a.contentWindow.document:jQuery.makeArray(a.childNodes)" }, function(i,n){ jQuery.fn[ i ] = function(a) { var ret = jQuery.map(this,n); if ( a && typeof a == "string" ) ret = jQuery.multiFilter(a,ret); return this.pushStack( jQuery.unique(ret) ); }; }); jQuery.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function(i,n){ jQuery.fn[ i ] = function(){ var a = arguments; return this.each(function(){ for ( var j = 0, al = a.length; j < al; j++ ) jQuery(a[j])[n]( this ); }); }; }); jQuery.each( { removeAttr: function( key ) { jQuery.attr( this, key, "" ); this.removeAttribute( key ); }, addClass: function(c){ jQuery.className.add(this,c); }, removeClass: function(c){ jQuery.className.remove(this,c); }, toggleClass: function( c ){ jQuery.className[ jQuery.className.has(this,c) ? "remove" : "add" ](this, c); }, remove: function(a){ if ( !a || jQuery.filter( a, [this] ).r.length ) { jQuery.removeData( this ); this.parentNode.removeChild( this ); } }, empty: function() { // Clean up the cache jQuery("*", this).each(function(){ jQuery.removeData(this); }); while ( this.firstChild ) this.removeChild( this.firstChild ); } }, function(i,n){ jQuery.fn[ i ] = function() { return this.each( n, arguments ); }; }); jQuery.each( [ "Height", "Width" ], function(i,name){ var n = name.toLowerCase(); jQuery.fn[ n ] = function(h) { return this[0] == window ? jQuery.browser.safari && self["inner" + name] || jQuery.boxModel && Math.max(document.documentElement["client" + name], document.body["client" + name]) || document.body["client" + name] : this[0] == document ? Math.max( document.body["scroll" + name], document.body["offset" + name] ) : h == undefined ? ( this.length ? jQuery.css( this[0], n ) : null ) : this.css( n, h.constructor == String ? h : h + "px" ); }; }); 8.通过extend方法,为jQuery类添加了解析表达式部分的方法: var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? "(?:[\\w*_-]|\\\\.)" : "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)", quickChild = new RegExp("^>\\s*(" + chars + "+)"), quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"), quickClass = new RegExp("^([#.]?)(" + chars + "*)"); jQuery.extend({ expr: { "": "m[2]=='*'||jQuery.nodeName(a,m[2])", "#": "a.getAttribute('id')==m[2]", ... 9.现在,定义jQuery.event对象: jQuery.event = { add: function guid:1, global:{} remove:function trigger:function handle:function fix:function } 10开始定义jQuery对象的事件相关的方法 jQuery.fn.extend({ bind:function one:function ... }) 11定义了jQuery的启动(dom load)的处理方法 jQuery.extend({ isReady:false readyList:[] ready:function(){} } 12通过each方法,非常技巧的实现了绑定事件的处理 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + "submit,keydown,keypress,keyup,error").split(","), function(i,o){ jQuery.fn[o] = function(f){ return f ? this.bind(o, f) : this.trigger(o); }; }); 13定义bindReady方法 14开始实现jQuery对象的ajax方法 15.通过each方法,非常技巧的实现了绑定ajax事件的处理 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){ jQuery.fn[o] = function(f){ return this.bind(o, f); }; }); 16开始实现jQuery类的ajax方法 17jQuery对象的show hide等界面效果方法的定义 18queue函数的定义 var queue = function( elem, type, array ) { if ( !elem ) return; var q = jQuery.data( elem, type + "queue" ); if ( !q || array ) q = jQuery.data( elem, type + "queue", array ? jQuery.makeArray(array) : [] ); return q; }; 19jQuery对象的dequeu方法的实现 jQuery.fn.dequeue = function(type){ type = type || "fx"; return this.each(function(){ var q = queue(this, type); q.shift(); if ( q.length ) q[0].apply( this ); }); }; 20.jQuery类的speed方法、easing对象、timers数组和fx构建器的定义 21jQuery.fx的原型函数prototype的定义的实现 22jQuery.fx.step对象的定义 23.jQuery.offset方法的实现 |