当页面加载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方法的实现
|