在正式深入jQuery的核心功能选择器之前,还有一些方法,基本都是数组方法,用于遴选更具体的需要,如获得某个元素的所有祖选元素啦,等等。接着是其缓存机制data。
001. //去除两边的空白 002. trim: function( text ) { 003. return (text || "").replace( /^\s+|\s+$/g, "" ); 004. }, 005. //转换成数组,很大众的方法 006. makeArray: function( array ) { 007. var ret = []; 008. if( array != null ){ 009. var i = array.length; 010. // The window, strings (and functions) also have 'length' 011. if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) 012. ret[0] = array;//就只有一元素 013. else014. while( i )//处理数组 015. ret[--i] = array[i]; 016. } 017. return ret; 018. }, 019. //判断是否在数组中,类似indexOf 020. inArray: function( elem, array ) { 021. for ( var i = 0, length = array.length; i < length; i++ ) 022. // Use === because on IE, window == document 023. if ( array[ i ] === elem ) 024. return i; 025. return -1; 026. }, 027. //把新元素或第二个数组加入第一个数组中 028. //类似数组的concat 029. merge: function( first, second ) { 030. // We have to loop this way because IE & Opera overwrite the length 031. // expando of getElementsByTagName 032. var i = 0, elem, pos = first.length; 033. // Also, we need to make sure that the correct elements are being returned 034. // (IE returns comment nodes in a '*' query) 035. if ( !jQuery.support.getAll ) { 036. while ( (elem = second[ i++ ]) != null ) 037. if ( elem.nodeType != 8 ) 038. first[ pos++ ] = elem; 039. } else040. while ( (elem = second[ i++ ]) != null ) 041. first[ pos++ ] = elem; 042. return first; 043. }, 044. //过滤重复元素,用done这个普通对象做过滤器(因为键如果同名将被覆盖掉) 045. unique: function( array ) { 046. var ret = [], done = {}; 047. try { 048. for ( var i = 0, length = array.length; i < length; i++ ) { 049. var id = jQuery.data( array[ i ] ); 050. if ( !done[ id ] ) { 051. done[ id ] = true; 052. ret.push( array[ i ] ); 053. } 054. } 055. } catch( e ) { 056. ret = array; 057. } 058. return ret; 059. }, 060. //类似数组的filter,这方法起得真不好,通常这都是与正则有关的…… 061. //$.grep( [0,1,2], function(n,i){ 062. // return n > 0; 063. //}); 064. //[1, 2] 065. grep: function( elems, callback, inv ) { 066. var ret = []; 067. // Go through the array, only saving the items 068. // that pass the validator function 069. //写法很特别,callback之前的!是为了防止回调函数没有返回值 070. //javascript默认没有返回值的函数都返回undefined,这样一搞 071. //就变成true,原来返回true的变成false,我们需要负负得正,中和一下 072. //于是!=出场了,而inv也是未必存在的,用!强制转换成布尔 073. for ( var i = 0, length = elems.length; i < length; i++ ) 074. if ( !inv != !callback( elems[ i ], i ) ) 075. ret.push( elems[ i ] ); 076. return ret; 077. }, 078. //就是数组中的map 079. map: function( elems, callback ) { 080. var ret = []; 081. // Go through the array, translating each of the items to their 082. // new value (or values). 083. for ( var i = 0, length = elems.length; i < length; i++ ) { 084. var value = callback( elems[ i ], i ); 085. if ( value != null ) 086. ret[ ret.length ] = value; 087. } 088. return ret.concat.apply( [], ret ); 089. } 090.}); 091.// jQuery.browser下面的方法已经被废弃了,这些都是为兼容以前的版本与插件用 092.var userAgent = navigator.userAgent.toLowerCase(); 093.// Figure out what browser is being used 094.jQuery.browser = { 095. version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1], 096. safari: /webkit/.test( userAgent ), 097. opera: /opera/.test( userAgent ), 098. msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), 099. mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) 100.}; 101.//把以下方法parent,parents,next……添加到jQuery的原型上去,都是一些过滤方法 102.jQuery.each({ 103. parent: function(elem){return elem.parentNode;}, 104. parents: function(elem){return jQuery.dir(elem,"parentNode");}, 105. next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, 106. prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, 107. nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, 108. prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, 109. siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, 110. children: function(elem){return jQuery.sibling(elem.firstChild);}, 111. contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} 112.}, function(name, fn){ 113. jQuery.fn[ name ] = function( selector ) {//方法体 114. var ret = jQuery.map( this, fn ); 115. if ( selector && typeof selector == "string" ) 116. ret = jQuery.multiFilter( selector, ret ); 117. return this.pushStack( jQuery.unique( ret ), name, selector ); 118. }; 119.}); 120.//把以下方法appendTo,prependTo,insertBefore……添加到jQuery的原型上去, 121.//利用已有的append,prepend……方法构建 122.jQuery.each({ 123. appendTo: "append", 124. prependTo: "prepend", 125. insertBefore: "before", 126. insertAfter: "after", 127. replaceAll: "replaceWith"128.}, function(name, original){ 129. jQuery.fn[ name ] = function( selector ) { 130. var ret = [], insert = jQuery( selector ); 131. for ( var i = 0, l = insert.length; i < l; i++ ) { 132. var elems = (i > 0 ? this.clone(true) : this).get(); 133. jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 134. ret = ret.concat( elems ); 135. } 136. return this.pushStack( ret, name, selector ); 137. }; 138.}); 139. //一些重要常用的静态方法 140. jQuery.each({ 141. removeAttr: function( name ) { 142. jQuery.attr( this, name, "" ); 143. if (this.nodeType == 1) 144. this.removeAttribute( name ); 145. }, 146. addClass: function( classNames ) { 147. jQuery.className.add( this, classNames ); 148. }, 149. removeClass: function( classNames ) { 150. jQuery.className.remove( this, classNames ); 151. }, 152. toggleClass: function( classNames, state ) { 153. if( typeof state !== "boolean" ) 154. state = !jQuery.className.has( this, classNames ); 155. jQuery.className[ state ? "add" : "remove" ]( this, classNames ); 156. }, 157. remove: function( selector ) { 158. if ( !selector || jQuery.filter( selector, [ this ] ).length ) { 159. // Prevent memory leaks 160. jQuery( "*", this ).add([this]).each(function(){ 161. jQuery.event.remove(this);//★★★★★ 162. jQuery.removeData(this); 163. }); 164. if (this.parentNode) 165. this.parentNode.removeChild( this ); 166. } 167. }, 168. empty: function() { 169. // Remove element nodes and prevent memory leaks 170. jQuery(this).children().remove(); 171. // Remove any remaining nodes 172. while ( this.firstChild ) 173. this.removeChild( this.firstChild ); 174. } 175. }, function(name, fn){ 176. jQuery.fn[ name ] = function(){ 177. return this.each( fn, arguments ); 178. }; 179. }); 180. //将带单位的数值去掉单位 181. // Helper function used by the dimensions and offset modules 182. function num(elem, prop) { 183. return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; 184. }接着下来看jQuery的缓存机制,jQuery的性能很大部分依仗于它。
001.var expando = "jQuery" + now(), uuid = 0, windowData = {}; 002.jQuery.extend({ 003. cache: {}, 004. data: function( elem, name, data ) { 005. //坚决不染指window 006. elem = elem == window ? 007. windowData : 008. elem; 009. //在elem上设置一个变量 010. var id = elem[ expando ]; 011. // Compute a unique ID for the element 012. if ( !id ) 013. // 同时为id,elem[expando]赋值,值为单一数字 014. id = elem[ expando ] = ++uuid; 015. // Only generate the data cache if we're 016. // trying to access or manipulate it 017. if ( name && !jQuery.cache[ id ] ) 018. //在jQuery.cache上开辟一个对象,专门用于储存与那个elem有关的东西 019. jQuery.cache[ id ] = {}; 020. // Prevent overriding the named cache with undefined values 021. if ( data !== undefined )//data必须定义 022. jQuery.cache[ id ][ name ] = data; 023. // Return the named cache data, or the ID for the element 024. //根据第二个参数是否存在决定返回的是缓存数据还是element的特别ID 025. return name ? 026. jQuery.cache[ id ][ name ] : 027. id; 028. }, 029. //移除缓存数据 030. removeData: function( elem, name ) { 031. elem = elem == window ? 032. windowData : 033. elem; 034. var id = elem[ expando ]; 035. // If we want to remove a specific section of the element's data 036. if ( name ) { 037. if ( jQuery.cache[ id ] ) { 038. // Remove the section of cache data 039. delete jQuery.cache[ id ][ name ]; 040. // If we've removed all the data, remove the element's cache 041. name = ""; 042. for ( name in jQuery.cache[ id ] ) 043. break; 044. if ( !name ) 045. jQuery.removeData( elem ); 046. } 047. // Otherwise, we want to remove all of the element's data 048. } else { 049. // Clean up the element expando 050. try { 051. //IE不能直接用delete去移除,要用removeAttribute 052. delete elem[ expando ]; 053. } catch(e){ 054. // IE has trouble directly removing the expando 055. // but it's ok with using removeAttribute 056. if ( elem.removeAttribute ) 057. elem.removeAttribute( expando ); 058. } 059. // Completely remove the data cache 060. //用缓存体中把其索引值也移掉 061. delete jQuery.cache[ id ]; 062. } 063. }, 064. //缓存元素的类组数属性 065. //可读写 066. queue: function( elem, type, data ) { 067. if ( elem ){ 068. type = (type || "fx") + "queue"; 069. var q = jQuery.data( elem, type ); 070. if ( !q || jQuery.isArray(data) ) 071. //q是数组 072. q = jQuery.data( elem, type, jQuery.makeArray(data) ); 073. else if( data ) 074. q.push( data ); 075. } 076. return q; 077. }, 078. //对元素的类数组缓存进行dequeue(也就是shift) 079. dequeue: function( elem, type ){ 080. var queue = jQuery.queue( elem, type ), 081. fn = queue.shift(); 082. if( !type || type === "fx" ) 083. fn = queue[0]; 084. if( fn !== undefined ) 085. fn.call(elem); 086. } 087.}); 088.//让jQuery对象也能获得这种缓存能力 089.//都是用上面静态方法实现,最终的缓存体还是jQuery.cache 090.jQuery.fn.extend({ 091. data: function( key, value ){ 092. var parts = key.split("."); 093. parts[1] = parts[1] ? "." + parts[1] : ""; 094. if ( value === undefined ) { 095. var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); 096. if ( data === undefined && this.length ) 097. data = jQuery.data( this[0], key ); 098. return data === undefined && parts[1] ? 099. this.data( parts[0] ) : 100. data; 101. } else102. return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ 103. jQuery.data( this, key, value ); 104. }); 105. }, 106. removeData: function( key ){ 107. return this.each(function(){ 108. jQuery.removeData( this, key ); 109. }); 110. }, 111. queue: function(type, data){ 112. if ( typeof type !== "string" ) { 113. data = type; 114. type = "fx"; 115. } 116. if ( data === undefined ) 117. return jQuery.queue( this[0], type ); 118. return this.each(function(){ 119. var queue = jQuery.queue( this, type, data ); 120. if( type == "fx" && queue.length == 1 ) 121. queue[0].call(this); 122. }); 123. }, 124. dequeue: function(type){ 125. return this.each(function(){ 126. jQuery.dequeue( this, type ); 127. }); 128. } 129.});
posted on
浙公网安备 33010602011771号