jQuery 源碼 extend

expando:生成惟一的JQ字符串(內部)javascript

  做爲映射關係的,保證惟一的字符串。css

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

  alert($.expando);java

 

noConflict() : 防止衝突node

  $, JQuery,命名衝突問題。jquery

  var hugo = $.noConflict();json

  var $ = 58;  //給$複製windows

  hugo (function () {數組

    alert($);promise

  })

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;
相關文章
相關標籤/搜索