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

    //添加实例属性和方法
    jQuery.fn = jQuery.prototype = {
    	// 版本,使用方式:$().jquery弹出当前引入的jquery的版本
    	jquery: core_version,
    	// 修正指向问题(后有详解)
    	constructor: jQuery,
    
    	// 初始化和参数管理
    	init: function( selector, context, rootjQuery ) {
    		var match, elem;
    
    		// 写错之后的处理,如果写成: $(""), $(null), $(undefined), $(false),直接返回
    		if ( !selector ) {
    			return this;
    		}
    		// 对字符串进行处理
    		if ( typeof selector === "string" ) {
                // 如果是这种$('<li>')或$('<li>1</li><li>2</li>')
                if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
    			    // match = [ null, '<li>', null ];或者 match = [ null, '<li>1</li><li>2</li>', null ];
    			    match = [ null, selector, null ];
                 //如果是$('#div1') $('.box') $('div')  $('#div1 div.box')
    		    } else {
                    //$('.box') $('div') $('#div1 div.box')  match = null;
                    //$('#div1') match = ['#div1',null,'div1'];
                    //$('<li>hello')  match = ['<li>hello','<li>',null];
    			     match = rquickExpr.exec( selector );  //exec()后面详解
    		    }
                
                      // $('<li>')  $('#div1') //$('#div1')的上下文为空,即context为false
                 if ( match && (match[1] || !context) ) {	
    			   if ( match[1] ) {
                        // 如果是$('<li>',document)填写了第二个对象,并且第二个对象是原生,则直接返回该对象;$('<li>',$(document))如果返回的第二个对象是jQuery,则将它转换成原生的对象 
    					context = context instanceof jQuery ? context[0] : context;
    					// 1、jQuery.parseHTML()函数用于将HTML字符串解析为对应的DOM节点数组;使用一个HTML字符串创建一个数组的DOM节点
    					jQuery.merge( this, jQuery.parseHTML(
    						match[1],  //需要解析并转成DOM节点数组的HTML字符串
    						//指定在哪个Document中创建元素,默认为当前文档的document,可能是iframe
    						context && context.nodeType ? context.ownerDocument || context : document,
    						//true,Boolean类型指定传入的HTML字符串中是否包含脚本,默认为false
    						true
    					) );
    
    					// 1、rsingleTag.test( match[1] )匹配单标签,只能匹配<li>或<li></li>,其他都不行
    					// 2、jQuery.isPlainObject( context )函数用于判断指定参数是否是一个纯粹的对象。{ } 或new Object()或{ name: "CodePlayer"}
    					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
    						for ( match in context ) {
    							// jQuery.isFunction用于判断参数是否是一个函数
    							if ( jQuery.isFunction( this[ match ] ) ) {
    								//如果是函数就直接调用该函数,示例:$('<li></li>',{title : 'hi',html : 'abcd',css : {background:'red'}}).appendTo( 'ul' );其中html : 'abcd'就相当于this.html('abcd')
    								this[ match ]( context[ match ] );
    							} else {
    								//如果不是函数就直接添加属性
    								this.attr( match, context[ match ] );
    							}
    						}
    					}
    
    					return this;
    
    				//  $('#div1')选择元素
    				} else {
    					elem = document.getElementById( match[2] );
    
    					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;
    				}
    
    		
    			} else if ( !context || context.jquery ) {
    				return ( context || rootjQuery ).find( selector );
    			
    			} else {
    				return this.constructor( context ).find( selector );
    			}
    
    		//对DOM元素进行处理,$(this),$(document)。
    		//nodeType属性返回以数字值返回指定节点的节点类型。如果是元素节点,返回1;如果是属性节点,返回2
    		} else if ( selector.nodeType ) {
    			this.context = this[0] = selector;
    			this.length = 1;
    			return this;
    
    
            // 对函数进行处理
    		} else if ( jQuery.isFunction( selector ) ) {
    			// 如果是函数$(function(){}),返回$(document).ready(function(){});
    			return rootjQuery.ready( selector );
    		}
    	   // 对空对象或空数组进行处理
    		if ( selector.selector !== undefined ) {
    			this.selector = selector.selector;
    			this.context = selector.context;
    		}
            // jQuery.makeArray()函数用于将一个类数组对象转换为真正的数组对象(详解)
    		return jQuery.makeArray( selector, this );
    	},
    	// selector 存储选择字符串;
    	selector: "",
    	// length this对象的长度
    	length: 0,
    	// toArray 专数组
    	toArray: function() {
    		return core_slice.call( this );
    	},
    
    	// get 转原生合集
    	get: function( num ) {
    		return num == null ?
    
    			// Return a 'clean' array
    			this.toArray() :
    
    			// Return just the object
    			( num < 0 ? this[ this.length + num ] : this[ num ] );
    	},
    
    
    	// pushStack JQ对象的入栈(先进后出)
    	pushStack: function( elems ) {
    
    		// Build a new jQuery matched element set
    		var ret = jQuery.merge( this.constructor(), elems );
    
    		// Add the old object onto the stack (as a reference)
    		ret.prevObject = this;
    		ret.context = this.context;
    
    		// Return the newly-formed element set
    		return ret;
    	},
    
    
    	// each 遍历集合
    	each: function( callback, args ) {
    		return jQuery.each( this, callback, args );
    	},
    	// DOM加载接口
    	ready: function( fn ) {
    		jQuery.ready.promise().done( fn );
    
    		return this;
    	},
    	// 集合的截取
    	slice: function() {
    		return this.pushStack( core_slice.apply( this, arguments ) );
    	},
    	// 集合的第一项
    	first: function() {
    		return this.eq( 0 );
    	},
    	// 集合的最后一项
    	last: function() {
    		return this.eq( -1 );
    	},
    	// 集合的指定项
    	eq: function( i ) {
    		var len = this.length,
    			j = +i + ( i < 0 ? len : 0 );
    		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
    	},
    	// 返回新集合
    	map: function( callback ) {
    		return this.pushStack( jQuery.map(this, function( elem, i ) {
    			return callback.call( elem, i, elem );
    		}));
    	},
    	// 返回集合前一个状态
    	end: function() {
    		return this.prevObject || this.constructor(null);
    	},
    
    	// push、sort、splice内部使用
    	push: core_push,
    	sort: [].sort,
    	splice: [].splice
    };
    

    部分详解

    1、constructor: jQuery
    示例:

    // js源码在构造函数创建完就自动生成了
    function Aaa(){};
        Aaa.prototype.constructor = Aaa;
        var a = new Aaa();
        alert(a.constructor);  // function Aaa(){};
    
        Aaa.prototype.constructor = Array;
        alert(a.constructor);  // function Array() { [native code] }
    
        Aaa.prototype = {
            constructor : Aaa,
            name : 'hello',
            age : 30
        };
        var a1 = new Aaa();
        alert(a1.constructor);  // function Aaa(){};
    

    这个constructor属性非常容易被不小心修改掉,所以jquery需要修正指向

    2、match = rquickExpr.exec( selector )
    示例:

    var  rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/;
    var selector = "#div1";
    var match = rquickExpr.exec( selector );
    console.log(match);      //match = ['#div1',null,'div1'];
    

    exec() 方法就是用来检索字符串中正则表达式的匹配,如果匹配到了那么就返回一个存放有结果的数组,如果没有匹配到就返回一个null;
    match是数组,第0个元素是与正则表达式相匹配的文本,第1个元素是与正则表达式的第1个子表达式相匹配的文本(如果有的话),第2个元素是第2个子表达式相匹配的文本(如果有的话),第3个元素是第3个子表达式相匹配的文本(如果有的话),这里就是元素的ID,不包含#。

    3、jQuery.makeArray()
    var aDiv = document.getElementsByTagName('div');
    aDiv并不是一个真正的数组,可以用$.makeArray(aDiv)转成一个数组 ;$.makeArray(aDiv,{length:0})将它转成一个对象
    $([]) $({})

  • 相关阅读:
    记CentOS-7-x86_64-DVD-1503与Windows7单硬盘双系统的安装
    NetCFSvcUtil.exe and Windows 7
    qq 通信原理(转)
    Qt通过odbc读取excel数据
    Qt中gb2312/GBK的URL编解码函数
    Qt将表格table保存为excel(odbc方式)
    Qt根据类名创建对象(元对象反射)
    亲试,Windows平台上使用Qt5.2.1编写Android
    使用正则表达式限制swing (JTextField等) 的输入
    Winform的"透明"
  • 原文地址:https://www.cnblogs.com/fangnianqin/p/9875510.html
Copyright © 2011-2022 走看看