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', width:'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;

 

转载于:https://www.cnblogs.com/hgonlywj/p/4845479.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值