zoukankan      html  css  js  c++  java
  • jQuery 源码 extend

    expando:生成唯一的JQ字符串(内部)

      作为映射关系的,保证唯一的字符串。

      expando:"jquery" + (core_version + Math.random()).replace(/D/g, '');

      alert($.expando);

    noConflict() : 防止冲突

      $, JQuery,命名冲突问题。

      var hugo = $.noConflict();

      var $ = 58;  //给$复制

      hugo (function () {

        alert($);

      })

    hugo来代替$,现在$为123
    
      noConflict: function( deep ) {    //deep放弃JQuery的对外接口
            if ( window.$ === jQuery ) {
                window.$ = _$;
            }
    
            if ( deep && window.jQuery === jQuery ) {
                window.jQuery = _jQuery;
            }
    
            return jQuery;
        },

    返回的值就是JQuery对象,
    在上面定义过:  _$ = windows.$;
    $.noConflict(true);    //放弃JQuery

    isReady : DOM是否加载完成

    $(funciton () {  DOM加载完成,就开始运行
    
    })
    
    这里要区分window.onload和ready()方法。  onloads要等全部都加载完成,才开始运行。
    
      DOMContentLoader原生中DOM加载的事件。
    
    
    
    $(function() {})--->>> $(document).ready(function () {});  //这两个一样。
    $.ready();   //工具方法。这两个不是一样的。
    
    $().ready();  //这是实例方法。
      jQuery.ready.promise().done( fn );  //创建的是一个延迟对象。
    jQuery.ready.promise (obj) 防止外面去修改。promise只有三个状态。
    
    	if (document.readyState === 'complete') {
    		(1)
    		setTimeout(jQuery.ready);	//省掉时间参数,为了解决IE的问题。
    	}
    	else {
    		(2)
    		document.addEventListener("DOMContentLoaded", complete, false);
    		window.addEventListener("load", complete, false);
    	}
    
    	(1), (2)都调用read方法。--->>>> 
    		readyList.resolveWith(documnet, [jQuery]) //已完成!!!
    		---》》fn
    
    		complete是个函数,内嵌了两个removeEventListener;删除了load和DOMContentLoaded两个事件。然后调用jQuery.ready();
    	只会ready一次。
    ODM加载事件。
    延迟对象:promise状态是无法被修改的。
    jQuery判断DOM是否好了,用document.readyState == 'complete'来判断。
    
    一:
    	$(function(arg) {
    		alert(arg);
    	})
    
    二:
    	document.ready(function () {
    		; 
    	});
    
    三:
    	$(document).on('ready', function () {
    		;
    	})
    

     

     readyWait : 等待多少文件的计数器(内容)

    holdReady() : 推迟DOM触发

    $.holderReady(true);		//推迟加载事件
    $(function(arg) {
    	alert(arg);
    })
    $.holdReady(false);		//释放
    
    可以使用holdReady实现你想要的加载顺序
    比如:
    a.js
    alert(1);
    	
    	$.holdReady(true);	//推迟加载
    	$.getScript('a.js', funciton () {
    		$.holdReady(false);	//开启加载
    	})
    
    	$(function () {
    		alert(2);
    	});
    
    alert顺序为1 2 。如果没有holdReady,就是2,1.
    可以holdready多次。 
    
    	// Hold (or release) the ready event
    	holdReady: function( hold ) {	
    		if ( hold ) {	//true	释放。
    			jQuery.readyWait++;			//添加一个holdready
    		} else {		//false 添加。
    			jQuery.ready( true );
    		}
    	},
    

    ready : 准备DOM触发

    	ready: function( wait ) {
    
    		// Abort if there are pending holds or we're already ready
    		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
    			return;
    		}
    
    		// Remember that the DOM is ready
    		jQuery.isReady = true;
    
    		// If a normal DOM Ready event fired, decrement, and wait if need be
    		if ( wait !== true && --jQuery.readyWait > 0 ) {	//这里看到readyWait--为0的时候,才可以继续运行。
    			return;	 
    		}
    
    		// If there are functions bound, to execute
    		readyList.resolveWith( document, [ jQuery ] );
    
    		// Trigger any bound ready events
    		if ( jQuery.fn.trigger ) {
    			jQuery( document ).trigger("ready").off("ready");
    		
    		}
    	 }
    

    工具方法的调用都要加一个$ function hg() { } alert($.isFunction(hg)); //true 这里注意:在低版本的IE,不会返回function类型,返回object类型。 isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray() 数组 在ES5中,已经原生js判断数组的函数了。 Array.isArray() isArray: Array.isArray, isWindow() :是否是window对象 isWindow: function( obj ) { return obj != null && obj === obj.window; }, 这里解释一下:alert(true == null) //false 除了 undefined == null 和 null == null 是true,其他的都是false;null和undefined没有包装对象,无法添加方法。 除了undefined和null,其他都在后面判断。 === 判断是否是类型和值都相同。 window是全局变量,或者是浏览器窗口。window.open() isNumeric():是否是数字 isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }, 前半段,判断是不是NaN 后半段,判断是否是一个有限的数字。isFinite,超出了计算机能计算的数字,就返回false; (Number.MAX_VALUE 最大值) 判断是否可以转数字,并且是一个有限的数字。 type():判断数据类型 type: function( obj ) { if ( obj == null ) { //只有2种情况成立,就是null喝undefined。 return String( obj ); //返回字符串。 } return typeof obj === "object" || typeof obj === "function" ? class2type[ core_toString.call(obj) ] || "object" : typeof obj; }, var a = {}; alert($.type(a)); //这个比typeof要强大一些。 alert({}.toString.call([])); //object Array alert({}.toString.call([]) == '[object Array]'); //true alert({}.toString.call({}) == '[object Array]'); //false alert({}.toString.call(new Date) == '[object Date]'); //true 做类型判断的时候,尽量用这个来判断。 {}.toString.call(obj); //判断obj的类型。 isPlanObject():是否为对象自变量 //判断对象自变量 //有2种形式, json 和 new Object(); var obj = { name: 'hello'}; alert($.isPlainObject(obj)); isPlainObject: function( obj ) { //不是obj就返回,nodeType节点类型, //将DOM节点放入jQuery中,返回Object,但是DOM节点不是对象自变量 //window也不是对象自变量 if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } //例如传入,window.location对象,jQuery也返回对象。但是又不是对象自变量。 //首先判断是否有constructor这个属性,其次, //core_hasOwn 是hasOwnProperty。判断这个属性是不是自身的。 //isPrototypeOf是Object自己独有的属性,其他没有。 //判断属性跟原型之间的关系。 try { if ( obj.constructor && !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { return false; } } catch ( e ) { return false; } return true; }, //FFwindow.constructor 频繁调用,会产生泄漏。 isEmptyObject():是否为空对象 isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; }, var obj = []; var a = null; 都是空。没有属性跟方法。就是空。利用了for in 完成。 for in 必须是自身下面的属性和方法,系统自带的。 比如像,constructor 这种是无法被for in 循环得到的。

    error():抛出异常

    error: function( msg ) {
    throw new Error( msg ); //抛出自定义错误
    },

    $.error('这是错误');
    //判处异常就是提示的。

     parseHTML():解析节点

    //把一个字符串转化为节点。
    	parseHTML: function( data, context, keepScripts ) {
    		if ( !data || typeof data !== "string" ) {
    			return null;
    		}
    		if ( typeof context === "boolean" ) {
    			keepScripts = context;
    			context = false;
    		}
    		context = context || document;
    
    		var parsed = rsingleTag.exec( data ),
    			scripts = !keepScripts && [];
    
    		// 看是否是单标签
    		if ( parsed ) {
    			return [ context.createElement( parsed[1] ) ];
    		}
    
    		//多标签,文档碎片的形式,创建,然后一次性追加入文档。
    		parsed = jQuery.buildFragment( [ data ], context, scripts );
    
    		//判断是否有script标签。
    		if ( scripts ) {
    			jQuery( scripts ).remove();
    		}
    
    		return jQuery.merge( [], parsed.childNodes );	//返回一个dom节点,用merge转成数组。--》json
    	},
    
    
    var str = '<li></li><li></li></script>';
    console.log($.parseHTML(str, document, true));
    
    //三个参数,第一个是要解析的节点
    //第二个是 父节点,一定是document
    //第三个是,布尔值,是否存入sript标签
    
    		$('<li></li>')	//创建一个,
    				//调用
    			$.parseHTML();
    (1)单标签,就是直接createElement,	
    (2)多标签,就调用buildFragment。
    

     parseJSON():字符串解析为json


    注意,这个字符串一定要是一个严格Json,

    parseJSON: JSON.parse,
    还有一个eval,安全性上,parse比eval安全。parse是解析严格的json。

    将json--》str 方法是:JSON.stringify();

    这个事ES6,提供的方法,IE8以上的版本。

    var str = '{"name":"hello"}';
    alert($.parseJSON(str).name);

    parseXML解析XML,

        现在用的比较少了,用的json比较多。
    
        parseXML: function( data ) {
            var xml, tmp;
            if ( !data || typeof data !== "string" ) {
                return null;
            }
    
            // Support: IE9
            try {
                tmp = new DOMParser();
                xml = tmp.parseFromString( data , "text/xml" );
            } catch ( e ) {
                xml = undefined;
            }
    
            if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
                jQuery.error( "Invalid XML: " + data );
            }
            return xml;
        },

    noop空函数。

    noop: function() {},
    
    
    	function test() {
    
    		this.defaluts = {
    			<!-- show :function() {} -->
    			show :$.noop
    		}
    
    	}
    
    globalEval:全局解析JS,将局部变量变为全局变量。
    	将代码转为全局,代码是字符串
    globalEval: function( code ) {
    		var script,
    				indirect = eval;	//将eval变成局部变量,全局范围内可以找打
    
    		//先去掉前后空格
    		code = jQuery.trim( code );
    
    		//存在。
    		if ( code ) {
    			//查看是否包含严格模式。
    			//在严格模式下,是不支持eval解析。
    			//通过创建script标签来添加到head,然后在删除就可以了。
    
    			if ( code.indexOf("use strict") === 1 ) {
    				script = document.createElement("script");
    				script.text = code;
    				document.head.appendChild( script ).parentNode.removeChild( script );
    			} else 
    			{
    				//直接用eval来解析。
    			
    				indirect( code );		// indirect eval
    				//这里注意,eval和window.eval是有区别的,
    			}
    		}
    	},
    
    
    function test() {
      var newvar = true;
    }
    alert(newarr);  //undefined;
    
    function test() {
      jQuery.globalEval(" var newvar = true;");
    }
    
    alert(newarr);  //true;
    
    
    <!-- 在严格模式下面。 -->
    code = "var aaa = 'hgwj'";
    var script = document.createElement("script");
    script.text = code;
    document.head.appendChild( script ).parentNode.removeChild( script );
    <!-- document.head.appendChild( script ).parentNode.removeChild( script ); -->
    
    camelCase	//转驼峰
    	camelCase: function( string ) {
    		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
    	},
    
    (1)IE前面有前缀,需要注意,因为IE不识别, 第一个字母大写。 
    -ms-transform -->>  msTransform
    -moz-transform -->> moz-transform.
    
    	replace( rmsPrefix, "ms-" ):目的是把 -ms转换为ms。这样解决IE问题。
    	replace( rdashAlpha, fcamelCase )	//转驼峰。fcamelCase是对调函数。
    
    
    
    nodeName:是一个内部方法,是否为指定的节点名。
    	nodeName: function( elem, name ) {
    		//先判断是否有elem,然后再判断节点名称是否和name相等,
    		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    	},
    
    document.documentElement是html。判断这个标签是否和后面的一样。
    alert($.nodeName(document.documentElement, 'HTML'));	//true
    alert($.nodeName(document.body, 'HTML'));	//false
    alert($.nodeName(document.body, 'body'));	//false
    alert(document.body.nodeName);	//BODY
    
    
    
    
    each:循环,遍历集合。
    
    	//args是内部使用的参数。
    	each: function( obj, callback, args ) {
    		var value,
    			i = 0,
    			length = obj.length,	//判断是什么类型。
    			isArray = isArraylike( obj );	//判断是否是数组。
    
    		if ( args ) {	//内部使用。
    			if ( isArray ) {
    				for ( ; i < length; i++ ) {
    					value = callback.apply( obj[ i ], args );	//不定参数
    
    					if ( value === false ) {
    						break;
    					}
    				}
    			} else {
    				for ( i in obj ) {
    					value = callback.apply( obj[ i ], args );
    
    					if ( value === false ) {
    						break;
    					}
    				}
    			}
    
    		// A special, fast, case for the most common use of each
    		} else {	//外部使用
    			if ( isArray ) {	//是数组就for循环
    				for ( ; i < length; i++ ) {
    					value = callback.call( obj[ i ], i, obj[ i ] );		//定参
    
    					if ( value === false ) {
    						break;
    					}
    				}
    			} else {	//json形式,就用for in
    				for ( i in obj ) {
    					value = callback.call( obj[ i ], i, obj[ i ] );
    
    					if ( value === false ) {	//通过return false控制,结束循环。
    						break;
    					}
    				}
    			}
    		}
    
    		return obj;
    	},
    
    
    
    //使用each遍历数组
    var arr = ['a', 'b', 'c'];
    $.each(arr, function (key, value) {
      alert(key + " " + value);
    });
    
    //使用 $.each遍历json
    var json = {a:'aaa', b:'bbb', c:'ccc'};
    $.each(json, function (key, value) {
      alert(key + " " + value);
      return false;	//结束循环。
    });
    
    
    
    
    trim 		去前后,空白。
    	trim: function( text ) {
    		return text == null ? "" : core_trim.call( text );
    	},
    
    
    $.trim(' ht ');		//ht
    ES5,提供原生的trim方法。
    
    
    
    makeArray 将类数组,转换为真正的数组。
    
    	makeArray: function( arr, results ) {
    		var ret = results || [];
    
    		if ( arr != null ) {
    			if ( isArraylike( Object(arr) ) ) {
    				jQuery.merge( ret,		//进行合并数组
    					typeof arr === "string" ?
    					[ arr ] : arr
    				);
    			} else {
    				core_push.call( ret, arr );
    			}
    		}
    
    		return ret;
    	},
    
    
    使用:
    var lis = document.getElementsByTagName('li');
    console.log($.makeArray(lis));
    
    
    字符串Object(string);	-->  转换为json
    
    
    inArray	: 查询数组元素,类似于indexof	i是开始位置。
    	inArray: function( elem, arr, i ) {
    		return arr == null ? -1 : core_indexOf.call( arr, elem, i );
    	},
    
    
    var arr = ['a', 'b', 'c', 'd'];
    alert($.inArray('c', arr));	//2
    alert($.inArray('w', arr));		//-1
    
    
    
    
    merge: 合并数组
    
    	merge: function( first, second ) {
    		var l = second.length,
    			i = first.length,
    			j = 0;
    
    		//判断是不是number, json没有长度。
    
    		if ( typeof l === "number" ) {		//没有长度,就不能走
    			for ( ; j < l; j++ ) {
    				first[ i++ ] = second[ j ];
    			}
    		} else {
    			while ( second[j] !== undefined ) {
    				first[ i++ ] = second[ j++ ];
    			}
    		}
    
    		first.length = i;	//改变length长度。
    
    		return first;
    	},
    
    
    if : $.merge(['a', ['b'], ['c', 'd']]);
    
    
    else : $.merge(['a', 'b'], {0:"v", 1:'5'});
    
    或者, $.merge({0:'a', 1:'b'}, {0:"v", 1:'5'});
    
    
    变成: {0:, 1:....length:n};
    
    
    
    grep:过滤得到新数组
    
    	grep: function( elems, callback, inv ) {
    		var retVal,
    			ret = [],
    			i = 0,
    			length = elems.length;
    		inv = !!inv;	//加了2个!转换为false
    
    		for ( ; i < length; i++ ) {
    			retVal = !!callback( elems[ i ], i );	//返回真假, 参数是元素,和第几位。
    			if ( inv !== retVal ) {
    				ret.push( elems[ i ] );
    			}
    		}
    
    		return ret;
    	},
    
    使用:
    
    var arr = [1,2,3,4,5,6];
    //grep就是将满足返回条件为true的数组元素,
    arr = $.grep(arr, function (n , i) {
        return n > 2;
    });
    
    console.log(arr);   //[3, 4, 5, 6]
    
    第三个参数,true,就否,就是条件的反向。
    
    	undefined !! 两次,就变成了false。
    
    
    map:
    	map: function( elems, callback, arg ) {
    		var value,
    			i = 0,
    			length = elems.length,
    			isArray = isArraylike( elems ),
    			ret = [];
    
    		// Go through the array, translating each of the items to their
    		if ( isArray ) {	//数组。
    			for ( ; i < length; i++ ) {
    				value = callback( elems[ i ], i, arg );
    
    				if ( value != null ) {
    					ret[ ret.length ] = value;
    				}
    			}
    
    		// Go through every key on the object,
    		} else {
    			for ( i in elems ) {	//json for in
    				value = callback( elems[ i ], i, arg );
    
    				if ( value != null ) {
    					ret[ ret.length ] = value;
    				}
    			}
    		}
    
    		// 得到单一的数组,不是复合数组。
    		return core_concat.apply( [], ret );
    	},
    
    
    
    
    使用:
    var arr = [1,2,3,4,5,6];
    //grep就是将满足返回条件为true的数组元素,
    arr = $.map(arr, function (n , i) {
        return n + 1;
    });
    
    console.log(arr);   //[2, 3, 4, 5, 6, 7];
    
    
    guid
    	// A global GUID counter for objects
    	guid: 1
    
    guid唯一表示标识。
    
    
    proxy:改变this指向。
    
    	proxy: function( fn, context ) {
    		var tmp, args, proxy;
    
    		//判断是否是字符串
    		if ( typeof context === "string" ) {
    			tmp = fn[ context ];	//支持简化的写法。
    			context = fn;
    			fn = tmp;
    		}
    		/*
    			var obj = {
    				show:function () {
    					alert(this);
    				}
    			}
    			$(document).click(obj.show);	//this-》document
    			//如果想改变this,
    			$(document).click($proxy(obj.show, obj));	//this-》obj
    
    		简写的方式:
    			$(document).click($.proxy(obj, 'show')));
    
    			$.proxy(obj, 'show')-->转化为--》$.proxy(obj.show, obj);	
    		*/
    
    		if ( !jQuery.isFunction( fn ) ) {	//fn必须是函数。
    			return undefined;
    		}
    
    		args = core_slice.call( arguments, 2 );		//从第3个参数开始,
    		proxy = function() {	//还是调用apply
    			//core_slice.call( arguments )转化成真正的数组。
    			return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
    		};
    
    		//生成唯一的标识。
    		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
    
    		return proxy;
    	},
    
    
    使用
    function show(x, y) {
      alert(this);
      alert(x);
      alert(y);
    }
    
    //传递参数的三种方式。
    
    $.proxy(show, document)(1, 2);		//这里的this指向了document
    $.proxy(show, document, 2, 4);		//这里的this指向了document, 传入参数。
    $.proxy(show, document, 2)(4);		//这里的this指向了document, 传入参数。
    
    
    
    access:多功能的值操作,这个要多体会。
    	
    	$().css(); $().attr();	//可以获取,或者设置参数。
    
    $('div1').css({background:'red',color:'blue', '200px'});
    
    
    	//使用在css,这种当中,判断是否是获取,还是赋值。
    	//fn回调函数,
    	//key: 类似background,
    	//value:blue
    	//chainable: true,false 设置或者获取。
    
    	access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
    		var i = 0,
    			length = elems.length,
    			//key与空进行比较,如果有值,就返回false
    			bulk = key == null;
    
    		// 设定多组值。是json,多组值, 就是设定属性。
    		if ( jQuery.type( key ) === "object" ) {
    			chainable = true;	//设定
    			for ( i in key ) {
    				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
    			}
    
    		// 设定一组值。
    		} else if ( value !== undefined ) {
    			chainable = true;
    
    			//判断value是否是函数,
    			if ( !jQuery.isFunction( value ) ) {
    				raw = true;
    			}
    
    			//如果没有key值,就
    			if ( bulk ) {
    				// Bulk operations run against the entire set
    				if ( raw ) {
    					fn.call( elems, value );
    					fn = null;
    
    				// ...except when executing function values
    				} else {
    					bulk = fn;
    					fn = function( elem, key, value ) {
    						return bulk.call( jQuery( elem ), value );
    					};
    				}
    			}
    
    			//fn是否存在。
    			if ( fn ) {
    				for ( ; i < length; i++ ) {
    					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
    				}
    			}
    		}
    
    		return chainable ?
    			elems :
    
    			// Gets
    			bulk ?
    				fn.call( elems ) :
    				length ? fn( elems[0], key ) : emptyGet;
    	},
    
    
    now:获取当前时间。时间戳
    
    now: Date.now,	 //跟getTime()差不多。
    
    
    
    swap: CSS交换。
    
    	swap: function( elem, options, callback, args ) {
    		var ret, name,
    			old = {};
    
    		//保存当前样式
    		//设定预先设定样式。
    		for ( name in options ) {	
    			old[ name ] = elem.style[ name ];
    			elem.style[ name ] = options[ name ];
    		}
    
    		//获取
    		ret = callback.apply( elem, args || [] );
    
    		//还原保存样式
    		for ( name in options ) {
    			elem.style[ name ] = old[ name ];
    		}
    
    		return ret;
    	}
    
    
    $('div1').css('widht');
    $('div1').get(0).offsetWidth;
    如果dispaly为none。原生js获取不到了
    jQuery就可以获取隐藏元素的值,用的就是swap获取的。
    先隐藏到元素显示,然后再隐藏。
    用 visibility 和 position:absolubte;
    
  • 相关阅读:
    Java泛型方法
    HashMap,LinkedHashMap和TreeMap的区别
    HashSet,TreeSet和LinkedHashSet的区别
    Java中Arrays.sort()和Collections.sort()
    Java基础面试集合
    面试:字符串中的相关试题
    Hadoop相关知识整理系列之一:HBase基本架构及原理
    Ubuntu 15.10环境下安装Hive
    机器学习相关知识整理系列之三:Boosting算法原理,GBDT&XGBoost
    机器学习相关知识整理系列之二:Bagging及随机森林
  • 原文地址:https://www.cnblogs.com/hgonlywj/p/4845479.html
Copyright © 2011-2022 走看看