jQuery 分析中出了很多疑问,都不能解决,代码能看懂,但搞不明白为什么那么使用.这是一件很头痛的事儿.
jQuery 是一个很好的js库,优秀的原因是因为它有个好的思想,而我却看不明白.
/* * jQuery1.4.1 代码分析 isw2 zhoux */ //多库共存,数据缓存,队列控制 (function( window, undefined ) { var jQuery = function( selector, context ) { _jQuery = window.jQuery,// 记录原始的jQuery对象用于多库共存 _$ = window.$// 记录原始的$对象用于多库共存 }; // 多库共存 // 括展jQuery 对象本身 jQuery.extend({ noConflict: function( deep ) { window.$ = _$;// $的控制权让渡给第一个实现它的那个库 if ( deep ) { window.jQuery = _jQuery;// jQuery的控制权让渡给第一个实现它的那个库,这也是jQuery 多用jQuery 而不用$的原因 } return jQuery; } }); // 数据缓存 // 括展jQuery 方法 jQuery.fn.extend({ data: function( key, value ) { if ( typeof key === "undefined" && this.length ) {// key 无值,通过length 判断数组 return jQuery.data( this[0] ); } else if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } var parts = key.split("."); parts[1] = parts[1] ? "." + parts[1] : ""; if ( value === undefined ) { var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);// ?为会么要triggerHandler? if ( data === undefined && this.length ) { data = jQuery.data( this[0], key ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } else { return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {// 为什么要trigger setData? jQuery.data( this, key, value ); }); } }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); var expando = "jQuery" + now(), uuid = 0, windowData = {};// 初始化时expando获取唯一值,在jQuery // 中全局 var emptyObject = {}; function now() { return (new Date).getTime(); } jQuery.extend({ cache: {}, expando:expando, noData: {// 不可存放数据的element 对象nodeName "embed": true,// 多媒体 "object": true, "applet": true }, data: function( elem, name, data ) {// 在元素上存放数据 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {// 检查节点是否可以存放Date return; } elem = elem == window ? windowData : elem; var id = elem[ expando ], cache = jQuery.cache, thisCache; if ( !name && !id ) {// name,elem.expando为空,用于jQuery.data(elem),且elem data == null情况 return null; } if ( !id ) {// elem.expando 为空 id = ++uuid;// id !=null 且唯一 } if ( typeof name === "object" ) { elem[ expando ] = id; thisCache = cache[ id ] = jQuery.extend(true, {}, name);// ? } else if ( cache[ id ] ) {// 如果已有值 thisCache = cache[ id ];// 此时cache[id]的值为thisCache } else if ( typeof data === "undefined" ) { thisCache = emptyObject; } else { thisCache = cache[ id ] = {};// 此时cache[id]的值为thisCache } if ( data !== undefined ) {// 防止一个undefined的值覆盖原有数据 elem[ expando ] = id; thisCache[ name ] = data;// 即cache[id]=data } /* * var value = $.cache; * for(var temp in value){ * for(var tempA in value[temp]){ * alert("$.cache["+tempA+"]:"+value[temp][tempA]); * } } * 可以查看结果 */ return typeof name === "string" ? thisCache[ name ] : thisCache; }, removeData: function( elem, name ) { if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { return; } elem = elem == window ? windowData : elem; var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; if ( name ) { if ( thisCache ) {// 根据name 删除,否则删除expando delete thisCache[ name ];// delete if ( jQuery.isEmptyObject(thisCache) ) {//isEmptyObject 测试对象是否是空对象 jQuery.removeData( elem ); } } } else {// 通过delete 删除expando 如果不能则用removeAttribute(javascript 方法)操作 try { delete elem[ expando ]; } catch( e ) { if ( elem.removeAttribute ) { elem.removeAttribute( expando ); } } delete cache[ id ]; } } }); //队列控制 // 括展jQuery 对象本身 jQuery.extend({ queue: function( elem, type, data ) { if ( !elem ) { return; } type = (type || "fx") + "queue"; var q = jQuery.data( elem, type );//调用jQuery.data()查询elem 上type 的数据 if ( !data ) { return q || []; } if ( !q || jQuery.isArray(data) ) { q = jQuery.data( elem, type, jQuery.makeArray(data) );//调用jQuery.data(),存入data } else { q.push( data ); } return q; }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(); if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { if ( type === "fx" ) { queue.unshift("inprogress"); } fn.call(elem, function() { jQuery.dequeue(elem, type); }); } } }); // 括展jQuery 方法 jQuery.fn.extend({ queue: function( type, data ) { if ( typeof type !== "string" ) { data = type; type = "fx"; } if ( data === undefined ) { return jQuery.queue( this[0], type ); } return this.each(function( i, elem ) { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); } }); window.jQuery = window.$ = jQuery; })