zoukankan      html  css  js  c++  java
  • jQuery源码学习笔记五

    在正式深入jQuery的核心功能选择器之前,还有一些方法,基本都是数组方法,用于遴选更具体的需求,如获得某个元素的所有祖选元素啦,等等。接着是其缓存机制data。

    //@author  司徒正美|なさみ|cheng http://www.cnblogs.com/rubylouvre/  All rights reserved
          //去除两边的空白
          trim: function( text ) {
            return (text || "").replace( /^\s+|\s+$/g, "" );
          },
          //转换成数组,很大众的方法
          makeArray: function( array ) {
            var ret = [];
            if( array != null ){
              var i = array.length;
              // The window, strings (and functions) also have 'length'
              if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
                ret[0] = array;//就只有一元素
              else
                while( i )//处理数组
                  ret[--i] = array[i];
            }
    
            return ret;
          },
          //判断是否在数组中,类似indexOf
          inArray: function( elem, array ) {
            for ( var i = 0, length = array.length; i < length; i++ )
            // Use === because on IE, window == document
              if ( array[ i ] === elem )
                return i;
    
            return -1;
          },
          //把新元素或第二个数组加入第一个数组中
          //类似数组的concat
          merge: function( first, second ) {
            // We have to loop this way because IE & Opera overwrite the length
            // expando of getElementsByTagName
            var i = 0, elem, pos = first.length;
            // Also, we need to make sure that the correct elements are being returned
            // (IE returns comment nodes in a '*' query)
            if ( !jQuery.support.getAll ) {
              while ( (elem = second[ i++ ]) != null )
                if ( elem.nodeType != 8 )
                  first[ pos++ ] = elem;
    
            } else
              while ( (elem = second[ i++ ]) != null )
                first[ pos++ ] = elem;
    
            return first;
          },
          //过滤重复元素,用done这个普通对象做过滤器(因为键如果同名将被覆盖掉)
          unique: function( array ) {
            var ret = [], done = {};
    
            try {
    
              for ( var i = 0, length = array.length; i < length; i++ ) {
                var id = jQuery.data( array[ i ] );
    
                if ( !done[ id ] ) {
                  done[ id ] = true;
                  ret.push( array[ i ] );
                }
              }
    
            } catch( e ) {
              ret = array;
            }
    
            return ret;
          },
          //类似数组的filter,这方法起得真不好,通常这都是与正则有关的……
          //$.grep( [0,1,2], function(n,i){
          //  return n > 0;
          //});
          //[1, 2]
          grep: function( elems, callback, inv ) {
            var ret = [];
            // Go through the array, only saving the items
            // that pass the validator function
            //写法很特别,callback之前的!是为了防止回调函数没有返回值
            //javascript默认没有返回值的函数都返回undefined,这样一搞
            //就变成true,原来返回true的变成false,我们需要负负得正,中和一下
            //于是!=出场了,而inv也是未必存在的,用!强制转换成布尔
            for ( var i = 0, length = elems.length; i < length; i++ )
              if ( !inv != !callback( elems[ i ], i ) )
                ret.push( elems[ i ] );
            return ret;
          },
          //就是数组中的map
          map: function( elems, callback ) {
            var ret = [];
    
            // Go through the array, translating each of the items to their
            // new value (or values).
            for ( var i = 0, length = elems.length; i < length; i++ ) {
              var value = callback( elems[ i ], i );
    
              if ( value != null )
                ret[ ret.length ] = value;
            }
    
            return ret.concat.apply( [], ret );
          }
        });
    
        // jQuery.browser下面的方法已经被废弃了,这些都是为兼容以前的版本与插件用
    
        var userAgent = navigator.userAgent.toLowerCase();
    
        // Figure out what browser is being used
        jQuery.browser = {
          version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
          safari: /webkit/.test( userAgent ),
          opera: /opera/.test( userAgent ),
          msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
          mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
        };
        //把以下方法parent,parents,next……添加到jQuery的原型上去,都是一些过滤方法
        jQuery.each({
          parent: function(elem){return elem.parentNode;},
          parents: function(elem){return jQuery.dir(elem,"parentNode");},
          next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
          prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
          nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
          prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
          siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
          children: function(elem){return jQuery.sibling(elem.firstChild);},
          contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
        }, function(name, fn){
          jQuery.fn[ name ] = function( selector ) {//方法体
            var ret = jQuery.map( this, fn );
    
            if ( selector && typeof selector == "string" )
              ret = jQuery.multiFilter( selector, ret );
    
            return this.pushStack( jQuery.unique( ret ), name, selector );
          };
        });
        //把以下方法appendTo,prependTo,insertBefore……添加到jQuery的原型上去,
        //利用已有的append,prepend……方法构建
        jQuery.each({
          appendTo: "append",
          prependTo: "prepend",
          insertBefore: "before",
          insertAfter: "after",
          replaceAll: "replaceWith"
        }, function(name, original){
          jQuery.fn[ name ] = function( selector ) {
            var ret = [], insert = jQuery( selector );
    
            for ( var i = 0, l = insert.length; i < l; i++ ) {
              var elems = (i > 0 ? this.clone(true) : this).get();
              jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
              ret = ret.concat( elems );
            }
    
            return this.pushStack( ret, name, selector );
          };
        });
    
         //一些重要常用的静态方法
          jQuery.each({
            removeAttr: function( name ) {
              jQuery.attr( this, name, "" );
              if (this.nodeType == 1)
                this.removeAttribute( name );
            },
    
            addClass: function( classNames ) {
              jQuery.className.add( this, classNames );
            },
    
            removeClass: function( classNames ) {
              jQuery.className.remove( this, classNames );
            },
    
            toggleClass: function( classNames, state ) {
              if( typeof state !== "boolean" )
                state = !jQuery.className.has( this, classNames );
              jQuery.className[ state ? "add" : "remove" ]( this, classNames );
            },
    
            remove: function( selector ) {
              if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
                // Prevent memory leaks
                jQuery( "*", this ).add([this]).each(function(){
                  jQuery.event.remove(this);//★★★★★
                  jQuery.removeData(this);
                });
                if (this.parentNode)
                  this.parentNode.removeChild( this );
              }
            },
    
            empty: function() {
              // Remove element nodes and prevent memory leaks
              jQuery(this).children().remove();
    
              // Remove any remaining nodes
              while ( this.firstChild )
                this.removeChild( this.firstChild );
            }
          }, function(name, fn){
            jQuery.fn[ name ] = function(){
              return this.each( fn, arguments );
            };
          });
          //将带单位的数值去掉单位
          // Helper function used by the dimensions and offset modules
          function num(elem, prop) {
            return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
          }
    

    接着下来看jQuery的缓存机制,jQuery的性能很大部分依仗于它。

    //@author  司徒正美|RestlessDream|なさみ|cheng http://www.cnblogs.com/rubylouvre/  All rights reserved
          var expando = "jQuery" + now(), uuid = 0, windowData = {};
    
          jQuery.extend({
            cache: {},
    
            data: function( elem, name, data ) {
              //坚决不染指window
              elem = elem == window ?
                windowData :
                elem;
              //在elem上设置一个变量
              var id = elem[ expando ];
    
              // Compute a unique ID for the element
              if ( !id )
              //  同时为id,elem[expando]赋值,值为单一数字
                id = elem[ expando ] = ++uuid;
    
              // Only generate the data cache if we're
              // trying to access or manipulate it
              if ( name && !jQuery.cache[ id ] )
              //在jQuery.cache上开辟一个对象,专门用于储存与那个elem有关的东西
                jQuery.cache[ id ] = {};
    
              // Prevent overriding the named cache with undefined values
              if ( data !== undefined )//data必须定义
                jQuery.cache[ id ][ name ] = data;
    
              // Return the named cache data, or the ID for the element
              //根据第二个参数是否存在决定返回的是缓存数据还是element的特别ID
              return name ?
                jQuery.cache[ id ][ name ] :
                id;
            },
            //移除缓存数据
            removeData: function( elem, name ) {
              elem = elem == window ?
                windowData :
                elem;
    
              var id = elem[ expando ];
    
              // If we want to remove a specific section of the element's data
              if ( name ) {
                if ( jQuery.cache[ id ] ) {
                  // Remove the section of cache data
                  delete jQuery.cache[ id ][ name ];
    
                  // If we've removed all the data, remove the element's cache
                  name = "";
    
                  for ( name in jQuery.cache[ id ] )
                    break;
    
                  if ( !name )
                    jQuery.removeData( elem );
                }
    
                // Otherwise, we want to remove all of the element's data
              } else {
                // Clean up the element expando
                try {
                  //IE不能直接用delete去移除,要用removeAttribute
                  delete elem[ expando ];
                } catch(e){
                  // IE has trouble directly removing the expando
                  // but it's ok with using removeAttribute
                  if ( elem.removeAttribute )
                    elem.removeAttribute( expando );
                }
    
                // Completely remove the data cache
                //用缓存体中把其索引值也移掉
                delete jQuery.cache[ id ];
              }
            },
            //缓存元素的类组数属性
            //可读写
            queue: function( elem, type, data ) {
              if ( elem ){
    
                type = (type || "fx") + "queue";
    
                var q = jQuery.data( elem, type );
    
                if ( !q || jQuery.isArray(data) )
                //q是数组
                  q = jQuery.data( elem, type, jQuery.makeArray(data) );
                else if( data )
                  q.push( data );
    
              }
              return q;
            },
            //对元素的类数组缓存进行dequeue(也就是shift)
            dequeue: function( elem, type ){
              var queue = jQuery.queue( elem, type ),
              fn = queue.shift();
    
              if( !type || type === "fx" )
                fn = queue[0];
    
              if( fn !== undefined )
                fn.call(elem);
            }
          });
          //让jQuery对象也能获得这种缓存能力
          //都是用上面静态方法实现,最终的缓存体还是jQuery.cache
          jQuery.fn.extend({
            data: function( key, value ){
              var parts = key.split(".");
              parts[1] = parts[1] ? "." + parts[1] : "";
    
              if ( value === undefined ) {
                var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
    
                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(){
                  jQuery.data( this, key, value );
                });
            },
    
            removeData: function( key ){
              return this.each(function(){
                jQuery.removeData( this, key );
              });
            },
            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(){
                var queue = jQuery.queue( this, type, data );
    
                if( type == "fx" && queue.length == 1 )
                  queue[0].call(this);
              });
            },
            dequeue: function(type){
              return this.each(function(){
                jQuery.dequeue( this, type );
              });
            }
          });
    
  • 相关阅读:
    无声的吐槽csdn
    成长
    最近忙的头发都油油的
    pycharm5工具免费分享及安装教程
    分布式版本控制git常见问题之gitignore冲突
    感觉自己还是太年轻,还有很多东西不会
    关于laravel5.2仓库的建立,以及简单调用
    乎,前所未有的挑战!
    嘿嘿,无聊的时候,来点好玩的,翻滚吧,杀马特!!!
    随便说说
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1607632.html
Copyright © 2011-2022 走看看