zoukankan      html  css  js  c++  java
  • jQuery源码学习之三 (jQUery对象的实例属性和方法)

    1、记录版本号 以及 修正constructor指向

       jquery: core_version,
       constructor: jQuery,
          因为jQuery.prototype={ ... } 这种写法将自动生成的jQuery.prototype.constructor属性覆盖删除,所以需要重新修正(指向其构造函数 jQuery)。

    2、init() 初始化方法:

         init()方法最终返回的是this -jQuery(其实是jQuery.prototype.init)方法的实例对象。

         实例对象继承了jQuery的实例属性和方法,且具有下标为0、1、2...、length的属性,从而 css()等方法可以利用 for...in循环处理 $() 集合中DOM元素。火狐下控制台截图如下:

        

          下面分步骤分析代码:

          ①if:传入无效的参数selector,直接返回this

        init: function( selector, context, rootjQuery ) {    
             var match, elem;
    	 if ( !selector ) {
    	     return this;
    	 };
             ...
         }

    
    

           ②if :传入的参数selector是字符串 rquickExpr是前面声明的变量:rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/;

              else if :传入的是DOM元素;

              else if: 传入的是函数,调用$("document").ready(function(){ ... });

              if :传入的是jQuery对象(存在属性selector)

    init: function( selector, context, rootjQuery ) {   
         ...
         if ( typeof selector === "string" ) {
            if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
                match = [ null, selector, null ];
            } else {
                match = rquickExpr.exec( selector );         
            }; 
          ... 
         }else if ( selector.nodeType ) {
                this.context = this[0] = selector;
                this.length = 1;
                return this;
            } else if ( jQuery.isFunction( selector ) ) {
                return rootjQuery.ready( selector );
            }
            if ( selector.selector !== undefined ) {
                this.selector = selector.selector;
                this.context = selector.context;
            }
            return jQuery.makeArray( selector, this );
     };
    

    上面代码中,if :情况包括类似 $("<div></div>")、$("<div>aaa</div><div>aaa</div>") 两中情况;

                         else :包括其余情况,例如:$(“</div>111”)、$("#id")、$(".class")、$("div")、$("#id .class div")等情况。requickExpr匹配的是$(“</div>111”)、$("#id")两种情况。如果传入的是$(“</div>111”),则match=["</div>111","</div>",null];如果传入的是$("#id"),则match=["#id",null,“id”];

         ③ 接下来是if esle 判断

             if :match不为null 且 match[1]不为null(传入的是标签形式),或match不为null且content为null(传入的是id形式,无需制定上下文);

             else if:  如果context没有传入或者传入是$()对象形式,则调用$().find ;

             else:如果context传入是原生jsDom对象形式,则调用$().find

    if ( match && (match[1] || !context) ) {
           
    }else if ( !context || context.jquery ) {     
        return ( context || rootjQuery ).find( selector );
    }else {            
        return this.constructor( context ).find( selector );
    }
    
    
    
    

      ④match不为null时,又分标签形式 和 id形式

         涉及到的函数:$.parseHTML 、$.merge、$.isPlainObject()

         $.parseHTML :将字符串转换为存储DOM节点的数组 。第一个参数为传入的字符串,第二个为指定的根节点,第三个是boolean值 (“<script></script>”是否可以转化为<script>标签),默认为false,不转换。

         $.merge:合并两个数组,在jQuery内部不仅可以合并数组,也可以合并类数组。例如:

    var  a={0:"aaa",1:"bbb",length:2} ,
         b=["ccc","ddd"];
    $.merge(a,b);   //{0:"aaa",1:"bbb",2:"ccc",3:"ddd",length:4};
            jQuery源码中先利用$.parseHTML 将传入的标签字符串转化为DOM节点数组,然后利用$.merge将DOM数组扩充到jQuery对象。

           $.isPlainObject():判断传入的参数是否是由 {}或new Object 创建的对象。


       代码分析:

       if:标签形式,(创建DOM并扩充到jQuery对象)

        if ( match[1] ) {
            //传入的第二个参数如果是jQuery对象,则转化为原生DOM
            context = context instanceof jQuery ? context[0] : context;
            //利用merge对jQuery实例对象进行扩充
            jQuery.merge( this, jQuery.parseHTML(
                match[1],
                context && context.nodeType ? context.ownerDocument || context : document,
                true
            ) );
            ...
        } else {
            ...
        }
    

    if:传入的第一个参数 是单标签字符串 且 第二个参数是纯对象 ,例如 $("<div>",{"html":"aaa","title":"aaa"});

    对第二个对象进行for in 循环,如果jQuery[match]是函数,调用jQuery[match](context[match]); 否则调用jQuery.attr(match,context[match])

    if ( match[1] ) {
        ...
        if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
    	  for ( match in context ) {
    		 if ( jQuery.isFunction( this[ match ] ) ) {
    			 this[ match ]( context[ match ] );
     		} else {
    			this.attr( match, context[ match ] );
    		}
    	}
        }
        return this;
    } else { 
        ...
    }

    
    else:传入的是#id 形式
    if ( match[1] ) {
       ...
    } else {
        elem = document.getElementById( match[2] );
        if ( elem && elem.parentNode ) {
            this.length = 1;
            this[0] = elem;
        }
    
        this.context = document;
        this.selector = selector;
        return this;
    }

    
    
    
    
    
    
    
    

    相关jQuery源码:

    jQuery.fn = jQuery.prototype = {
    	// The current version of jQuery being used
    	jquery: core_version,
    
    	constructor: jQuery,
    	init: function( selector, context, rootjQuery ) {
    		var match, elem;
    
    		// HANDLE: $(""), $(null), $(undefined), $(false)
    		if ( !selector ) {
    			return this;
    		}
    
    		// Handle HTML strings
    		if ( typeof selector === "string" ) {
    			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
    				// Assume that strings that start and end with <> are HTML and skip the regex check
    				match = [ null, selector, null ];
    
    			} else {
    				match = rquickExpr.exec( selector );
    			}
    
    			// Match html or make sure no context is specified for #id
    			if ( match && (match[1] || !context) ) {
    
    				// HANDLE: $(html) -> $(array)
    				if ( match[1] ) {
    					context = context instanceof jQuery ? context[0] : context;
    
    					// scripts is true for back-compat
    					jQuery.merge( this, jQuery.parseHTML(
    						match[1],
    						context && context.nodeType ? context.ownerDocument || context : document,
    						true
    					) );
    
    					// HANDLE: $(html, props)
    					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
    						for ( match in context ) {
    							// Properties of context are called as methods if possible
    							if ( jQuery.isFunction( this[ match ] ) ) {
    								this[ match ]( context[ match ] );
    
    							// ...and otherwise set as attributes
    							} else {
    								this.attr( match, context[ match ] );
    							}
    						}
    					}
    
    					return this;
    
    				// HANDLE: $(#id)
    				} else {
    					elem = document.getElementById( match[2] );
    
    					// Check parentNode to catch when Blackberry 4.6 returns
    					// nodes that are no longer in the document #6963
    					if ( elem && elem.parentNode ) {
    						// Inject the element directly into the jQuery object
    						this.length = 1;
    						this[0] = elem;
    					}
    
    					this.context = document;
    					this.selector = selector;
    					return this;
    				}
    
    			// HANDLE: $(expr, $(...))
    			} else if ( !context || context.jquery ) {
    				return ( context || rootjQuery ).find( selector );
    
    			// HANDLE: $(expr, context)
    			// (which is just equivalent to: $(context).find(expr)
    			} else {
    				return this.constructor( context ).find( selector );
    			}
    
    		// HANDLE: $(DOMElement)
    		} else if ( selector.nodeType ) {
    			this.context = this[0] = selector;
    			this.length = 1;
    			return this;
    
    		// HANDLE: $(function)
    		// Shortcut for document ready
    		} else if ( jQuery.isFunction( selector ) ) {
    			return rootjQuery.ready( selector );
    		}
    
    		if ( selector.selector !== undefined ) {
    			this.selector = selector.selector;
    			this.context = selector.context;
    		}
    
    		return jQuery.makeArray( selector, this );
    	},
    
    	// Start with an empty selector
    	selector: "",
    
    	// The default length of a jQuery object is 0
    	length: 0,
    
            ...
    };


  • 相关阅读:
    移动端 (基于jquery的3个)touch插件
    leaflet开源地图库源码 浏览器&移动设备判断(browser.js)备份
    移动端 常见问题整理 iOS下的 Fixed + Input 调用键盘的时候fixed无效问题解决方案
    百度echarts扇形图每个区块增加点击事件
    js 性能优化整理之 缓存变量
    移动端 延迟加载echo.js的使用
    js 性能优化整理之 高频优化
    css整理 background-size优化
    原生js 样式的操作整理
    百度地图展示分公司信息 (针对电视机)
  • 原文地址:https://www.cnblogs.com/hdchangchang/p/3965322.html
Copyright © 2011-2022 走看看