jquery.extend
jQuery.extend = jQuery.fn.extend = function () {var options, name, src, copy, copyIsArray, clone,//target为传入的一个参数 target = arguments[0] || {}, i = 1,//传入参数的个数 length = arguments.length,//首先默认为浅拷贝 deep = false;// Handle a deep copy situationif (typeof target === "boolean") {//当第一个参数是布尔值deep = target;//target第二个参数target = arguments[1] || {};// skip the boolean and the targeti = 2;}//当target不是object并且不是functionif (typeof target !== "object" && !jQuery.isFunction(target)) {target = {};}// extend jQuery itself if only one argument is passed//当是一个参数的时候$.extend({ccc:function(){}})if (length === i) {//target为init对象target = this;--i;}for (; i < length; i++) {// Only deal with non-null/undefined valuesif ((options = arguments[i]) != null) { // Extend the base object for (name in options) { src = target[name]; copy = options[name];// Prevent never-ending loop if (target === copy) { continue; }//// Recurse if we're merging plain objects or arrays//深拷贝 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 : {}; }// Never move original objects, clone them target[name] = jQuery.extend(deep, clone, copy);// Don't bring in undefined values } else if (copy !== undefined) {//将方法复制到当前对象 target[name] = copy; } }}}// Return the modified objectreturn target;};};
jquery.extend的使用
jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; },// Is the DOM ready to be used? Set to true once it occurs. isReady: false,// A counter to track how many items to wait for before// the ready event fires. See #6781 readyWait: 1,// Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } },// Handle when the DOM is ready ready: function( wait ) {// Either a released hold or an DOMready/load event and not yet ready//wait=true且jQuery.readyWait-1取非为true 或者wait为false jQuery.isReady为false if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\//当不存在body元素了,继续执行这个函数 if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); }// 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 ) { return; }// If there are functions bound, to execute readyList.fireWith( document, [ jQuery ] );// Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).off( "ready" ); } } }, bindReady: function() { console.log(readyList) if ( readyList ) { return; } readyList = jQuery.Callbacks( "once memory" );// Catch cases where $(document).ready() is called after the// browser event has already occurred. if ( document.readyState === "complete" ) {// Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); }// Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) {// Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );// A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false );// If IE event model is used } else if ( document.attachEvent ) {// ensure firing before onload,// maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded );// A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready );// If IE and not a frame// continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } },// See test/unit/core.js for details concerning isFunction.// Since version 1.3, DOM methods and functions like alert// aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, isWindow: function( obj ) { return obj != null && obj == obj.window; }, isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; },//纯对象的判断 isPlainObject: function( obj ) {// Must be an Object.// Because of IE, we also have to check the presence of the constructor property.// Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try {// Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) {// IE8,9 Will throw exceptions on certain host objects #9897 return false; }// Own properties are enumerated firstly, so to speed up,// if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) {//如果有元素就说明不是空的对象 return false; } return true; }, error: function( msg ) { throw new Error( msg ); }, parseJSON: function( data ) {//字符串转化为json if ( typeof data !== "string" || !data ) { return null; }// Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data );// Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); }// Make sure the incoming data is actual JSON// Logic borrowed from http://json.org/json2.js if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return ( new Function( "return " + data ) )(); } jQuery.error( "Invalid JSON: " + data ); },// Cross-browser xml parsing parseXML: function( data ) { if ( typeof data !== "string" || !data ) { return null; } var xml, tmp; try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } } catch( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {},// Evaluates a script in a global context// Workarounds based on findings by Jim Driscoll// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && rnotwhite.test( data ) ) {// We use execScript on Internet Explorer// We use an anonymous function so that context is window// rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } },// Convert dashed to camelCase; used by the css and data modules// Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); },//例如当string为“-ms-aaaa” 得到的是msAaa;//rmsPrefix = /^-ms-/,第一个replace结束后得到 ms-aaa//rdashAlpha = /-([a-z]|[0-9])/ig,第二个replace 匹配了-a fcamelCase(all,letter,index)//all为-a,letter为$1,为a,index=2 开始匹配的位置,从0开始 nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); },// args is for internal usage only each: function( object, callback, args ) { var name, i = 0,//有长度 length = object.length,//json对象的遍历 isObj = length === undefined || jQuery.isFunction( object );//args为真 if ( args ) { if ( isObj ) { for ( name in object ) {//举个例子:function add(b){console.log(b);}//$.each({'aaa':{ccc:1,'bbb':222}},add,['aaa']);//传递一个直接的参数,进行操作 if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) {//传递一个直接的参数,进行操作 if ( callback.apply( object[ i++ ], args ) === false ) { break; } } }// A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) {//$.each([1,3,5,6],function(i,v){}) if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; },// Use native String.trim function wherever possible trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } :// Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); },// results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) {// The window, strings (and functions) also have 'length'// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 var type = jQuery.type( array ); if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array, i ) { var len; if ( array ) { if ( indexOf ) { return indexOf.call( array, elem, i ); }//首先执行 i < 0 ? Math.max( 0, len + i ) : i//如果不存在就从0开始,否则从当i<0时,len+i开始,>0直接从开始 len = array.length; i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; for ( ; i < len; i++ ) {//返回所在位置 if ( i in array && array[ i ] === elem ) { return i; } } } return -1; }, merge: function( first, second ) {//jQuery.merge( ret, array );//传入的是init,和一个array console.log(first); console.log(second) var i = first.length, j = 0;//如果array是一个数组,在init的基础上再增加输入 if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i;//得到数组 return first; }, grep: function( elems, callback, inv ) {//grep() 方法是按照某种条件来过滤数组 var ret = [], retVal; inv = !!inv;// Go through the array, only saving the items// that pass the validator function//举个例子 var ccc=$.grep([1,2,4,'bb','cc'],function(v,i){return $.type(v)=='number'})//console.log(ccc);[1, 2, 4]//当最后参数设置为true是,到得到['bb','cc'] for ( var i = 0, length = elems.length; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; },// arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length,// jquery objects are treated as arrays//jquery对象也被当做是数组,如$('div') isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;// 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 ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } }// Flatten any nested arrays return ret.concat.apply( [], ret ); },// A global GUID counter for objects guid: 1,// Bind a function to a context, optionally partially applying any// arguments. proxy: function( fn, context ) { if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; }// Quick check to determine if target is callable, in the spec// this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; }// Simulated bind var args = slice.call( arguments, 2 ), proxy = function() { return fn.apply( context, args.concat( slice.call( arguments ) ) ); };// Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; },// Mutifunctional method to get and set values to a collection// The value/s can optionally be executed if it's a function access: function( elems, fn, key, value, chainable, emptyGet, pass ) { var exec, bulk = key == null, i = 0, length = elems.length;// Sets many values if ( key && typeof key === "object" ) { for ( i in key ) { jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); } chainable = 1;// Sets one value } else if ( value !== undefined ) {// Optionally, function values get executed if exec is true exec = pass === undefined && jQuery.isFunction( value ); if ( bulk ) {// Bulk operations only iterate when executing function values if ( exec ) { exec = fn; fn = function( elem, key, value ) { return exec.call( jQuery( elem ), value ); };// Otherwise they run against the entire set } else { fn.call( elems, value ); fn = null; } } if ( fn ) { for (; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } } chainable = 1; } return chainable ? elems :// Gets bulk ? fn.call( elems ) : length ? fn( elems[0], key ) : emptyGet; }, now: function() {//返回当前的时间 return ( new Date() ).getTime(); },// Use of jQuery.browser is frowned upon.// More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, browser: {}});// Populate the class2type mapjQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase()});browserMatch = jQuery.uaMatch( userAgent );if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version;}// Deprecated, use jQuery.browser.webkit insteadif ( jQuery.browser.webkit ) { jQuery.browser.safari = true;}