• jQuery架构(源码)分析


    ( function( global, factory ) {
    	"use strict";
    	if ( typeof module === "object" && typeof module.exports === "object" ) {
    		module.exports = global.document ?
    			factory( global, true ) :
    			function( w ) {
    				if ( !w.document ) {
    					throw new Error( "jQuery requires a window with a document" );
    				}
    				return factory( w );
    			};
    	} else {
    		factory( global );
    	}
    } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
    ........
    var version = "3.1.1",
    	/* 
    	 * jQuery构造函数创建时直接返回实例对象,此时就不需要
    	 * jQuery = function( selector, context ) {//构造函数 }
    	 * var a = new jQuery( selector, context);
    	 * 而是jQuery( selector, context)就得到一个jQuery初始化实例对象
    	 * 实际上这个构造函数并不是this指向的真实意义上的构造函数,而是工厂方式来创建实例。
    	 */
    	jQuery = function( selector, context ) {
    //jQuery.fn.init构建的出来的实例对象,就是jQuery对象
    //jQuery.fn.init.prototype = jQuery.fn;通过原型传递解决问题,把jQuery的原型传递给jQuery.fn.init.prototype
    return new jQuery.fn.init( selector, context ); }, 
    rtrim = /^[suFEFFxA0]+|[suFEFFxA0]+$/g, 
    rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g, 
    fcamelCase = function( all, letter ) { return letter.toUpperCase(); };
     /* jQuery原型 * jQuery.fn引用jQuery原型prototype,为jQuery实例添加方法和属性 * 例如,我们常用的$('class').each、$('div').eq(0)、$(arr).push()、$(arr).slice()等 */ 
    jQuery.fn = jQuery.prototype = {
        jquery: version, 
        constructor: jQuery, 
        length: 0, 
        toArray: function() { return slice.call( this ); }, 
        get: function( num ) { if ( num == null ) { return slice.call( this ); } return num < 0 ? this[ num + this.length ] : this[ num ]; }, 
        pushStack: function( elems ) { var ret = jQuery.merge( this.constructor(), elems ); ret.prevObject = this; return ret; }, 
       .......
    }; 
    /*
     * jQuery扩展插件 
    * jQuery.extend 对jQuery本身的属性和方法进行了扩展 
    * jQuery.fn.extend 对jQuery.fn的属性和方法进行了扩展 
    * 两种扩展其实是同一方法不同对象的调用 
    * eg:
    * var obj1 = {alert:function(){}} 
    * var obj2 = {consoleLog = function(){}} 
    * jQuery.fn.extend(obj1,obj2) 
    */
    jQuery.extend = jQuery.fn.extend = function() { 
        /* 
        * 形参对象arguments,支持多种参数形式 
        * eg: 
        * $.extend(obj1) 
        * $.extend(obj1,obj2,obj3,......) 
        * $.extend(true,obj1,obj2,obj3,......) 
        */
        var options, name, src, copy, copyIsArray, clone, 
        target = arguments[ 0 ] || {}, //初始化target,target引用形参arguments[0] 
        i = 1, 
        length = arguments.length, 
        deep = false;
        //第一个参数为布尔值时,表示是否深度拷贝 
         if ( typeof target === "boolean" ) {
           deep = target; //arguments[0],变量deep表示是否深度拷贝 target = arguments[ i ] || {};
          //target去第二个参数,即arguments[1]
           i++; 
        } 
        if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } 
        /* 
        * 如果只参数只传入一个对象时 
        * target引用this(jQuery.extend 或 jQuery.fn)
        * target添加方法就是给this添加方法
        * 即将传入对象整合到全局jQuery或jQuery.fn中
        */ 
    	if ( i === length ) {
    		target = this;
    		i--;
    	}
    
    	for ( ; i < length; i++ ) {
    		if ( ( options = arguments[ i ] ) != null ) {
    			for ( name in options ) {
    				//target继承参数的属性和方法
    				src = target[ name ];
    				copy = options[ name ];
    
    				if ( target === copy ) {
    					continue;
    				}
    				// 深度拷贝
    				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
    					( copyIsArray = jQuery.isArray( copy ) ) ) ) {
    					if ( copyIsArray ) {
    						copyIsArray = false;
    						clone = src && jQuery.isArray( src ) ? src : [];
    					} else {
    						clone = src && jQuery.isPlainObject( src ) ? src : {};
    					}
    					target[ name ] = jQuery.extend( deep, clone, copy );
    				// Don't bring in undefined values
    				} else if ( copy !== undefined ) {
    					target[ name ] = copy;
    				}
    			}
    		}
    	}
    	// 返回重载合并传入参数后的对象
    	return target;
    };
    
    
    /*
     * 为jQuery对象扩展方法
     */
    jQuery.extend( {
    	isArray: Array.isArray,
    	isWindow: function( obj ) {
    		return obj != null && obj === obj.window;
    	},
    	isNumeric: function( obj ) {
    		return ( type === "number" || type === "string" ) &&
    			!isNaN( obj - parseFloat( obj ) );
    	},
    	type: function( obj ) {
    		if ( obj == null ) {
    			return obj + "";
    		}
    		return typeof obj === "object" || typeof obj === "function" ?
    			class2type[ toString.call( obj ) ] || "object" :
    			typeof obj;
    	},
    	each: function( obj, callback ) {
    		var length, i = 0;
    		if ( isArrayLike( obj ) ) {
    			length = obj.length;
    			for ( ; i < length; i++ ) {
    				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
    					break;
    				}
    			}
    		} else {
    			for ( i in obj ) {
    				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
    					break;
    				}
    			}
    		}
    
    		return obj;
    	},
    	trim: function( text ) {
    		return text == null ?
    			"" :
    			( text + "" ).replace( rtrim, "" );
    	},
    	makeArray: function( arr, results ) {
    		var ret = results || [];
    		if ( arr != null ) {
    			if ( isArrayLike( Object( arr ) ) ) {
    				jQuery.merge( ret,
    					typeof arr === "string" ?
    					[ arr ] : arr
    				);
    			} else {
    				push.call( ret, arr );
    			}
    		}
    
    		return ret;
    	},
    	map: function( elems, callback, arg ) {
    		var length, value,
    			i = 0,
    			ret = [];
    		if ( isArrayLike( elems ) ) {
    			length = elems.length;
    			for ( ; i < length; i++ ) {
    				value = callback( elems[ i ], i, arg );
    
    				if ( value != null ) {
    					ret.push( value );
    				}
    			}
    		} else {
    			for ( i in elems ) {
    				value = callback( elems[ i ], i, arg );
    
    				if ( value != null ) {
    					ret.push( value );
    				}
    			}
    		}
    		return concat.apply( [], ret );
    	},
    .........
    } );
    
    if ( typeof Symbol === "function" ) {
    	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
    }
    
    
    .........
    jQuery.fn.ready = function( fn ) {
    	readyList
    		.then( fn )
    
    		// Wrap jQuery.readyException in a function so that the lookup
    		// happens at the time of error handling instead of callback
    		// registration.
    		.catch( function( error ) {
    			jQuery.readyException( error );
    		} );
    
    	return this;
    };
    
    jQuery.parseJSON = JSON.parse;
    
    if ( typeof define === "function" && define.amd ) {
    	define( "jquery", [], function() {
    		return jQuery;
    	} );
    }
    
    var _jQuery = window.jQuery,
    	_$ = window.$;
    jQuery.noConflict = function( deep ) {
    	if ( window.$ === jQuery ) {
    		window.$ = _$;
    	}
    	if ( deep && window.jQuery === jQuery ) {
    		window.jQuery = _jQuery;
    	}
    	return jQuery;
    };
    ........
    return jQuery;
    } );
    
    

      

     

    整理核心代码
    (function(){  
        //jQuery变量定义  
        var jQuery  = function(){...};  
        //jQuery原型定义(包含核心方法)                
        jQuery.fn = jQuery.prototype = {...};  
        //把jQuery的原型传递给jQuery.fn.init.prototype
        jQuery.fn.init.prototype = jQuery.fn;  
        //提供jQuery静态方法与对象方法的扩展函数  
        jQuery.extend = jQuery.fn.extend = function(){...};   
        //后面依次有多个对jQuery静态方法的扩展  
        jQuery.extend({...});  
        //后面依次有多个对jQuery对象方法的扩展  
        jQuery.fn.extend({...});  
        jQuery.support = (function() {...})();  
        //提供统一时间管理,jQuery内部使用,并不对外开放  
        jQuery.event = {...};  
        //Event类似于Java的POJO类.传递事件的对象  
        jQuery.Event = function( src, props ) {...};   
        //Sizzle选择器,一个框架,可独立使用。  
        (function(){  
            ...  
            jQuery.find = Sizzle;  
            ...  
        })();  
        ...  
        //将定义的jQuery定义为全局变量  
        window.jQuery = window.$ = jQuery;  
        ...  
    })();  
    

      

    以上就是jQuery的架构分析,jQuery提供的所有属性方法都是对jQuery对象,jQuery.fn对象的属性和方法进行了扩展

    这样的方式便于开发者维护代码,为JQ添加新方法时,不需要修改jQuery的原型,又可以快速扩展JQ功能。也为其他开发者提供了一个扩展接口

    以上为本前端菜鸟对jQuery的理解,如有偏颇,欢迎指教。

  • 相关阅读:
    Jenkins+ant循环执行jmeter文件
    Jmeter接口模版说明
    jenkins与远程服务器配置SSH免密登录
    xcode developer tools简介
    MySQL之模糊查询
    MySQL排名函数
    openblas下载安装与使用
    CVX安装使用
    AMD包下载及使用
    Python及相应软件安装
  • 原文地址:https://www.cnblogs.com/xiaomingSun/p/6824290.html
Copyright © 2020-2023  润新知