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方法的实现