JQuery 1.10.2源码分析学习5

上源码

jQuery.extend({
	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),

	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 ) {

		// Abort if there are pending holds or we're already ready
		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
			return;
		}

		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
		if ( !document.body ) {
			return setTimeout( jQuery.ready );
		}

		// 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.resolveWith( document, [ jQuery ] );

		// Trigger any bound ready events
		if ( jQuery.fn.trigger ) {
			jQuery( document ).trigger("ready").off("ready");
		}
	},

	// 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 ) {
		/* jshint eqeqeq: false */
		return obj != null && obj == obj.window;
	},

	isNumeric: function( obj ) {
		return !isNaN( parseFloat(obj) ) && isFinite( obj );
	},

	type: function( obj ) {
		if ( obj == null ) {
			return String( obj );
		}
		return typeof obj === "object" || typeof obj === "function" ?
			class2type[ core_toString.call(obj) ] || "object" :
			typeof obj;
	},

	isPlainObject: function( obj ) {
		var key;

		// 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 &&
				!core_hasOwn.call(obj, "constructor") &&
				!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
				return false;
			}
		} catch ( e ) {
			// IE8,9 Will throw exceptions on certain host objects #9897
			return false;
		}

		// Support: IE<9
		// Handle iteration over inherited properties before own properties.
		if ( jQuery.support.ownLast ) {
			for ( key in obj ) {
				return core_hasOwn.call( obj, key );
			}
		}

		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own.
		for ( key in obj ) {}

		return key === undefined || core_hasOwn.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		var name;
		for ( name in obj ) {
			return false;
		}
		return true;
	},

	error: function( msg ) {
		throw new Error( msg );
	},

	// data: string of html
	// context (optional): If specified, the fragment will be created in this context, defaults to document
	// keepScripts (optional): If true, will include scripts passed in the html string
	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 && [];

		// Single tag
		if ( parsed ) {
			return [ context.createElement( parsed[1] ) ];
		}

		parsed = jQuery.buildFragment( [ data ], context, scripts );
		if ( scripts ) {
			jQuery( scripts ).remove();
		}
		return jQuery.merge( [], parsed.childNodes );
	},

	parseJSON: function( data ) {
		// Attempt to parse using the native JSON parser first
		if ( window.JSON && window.JSON.parse ) {
			return window.JSON.parse( data );
		}

		if ( data === null ) {
			return data;
		}

		if ( typeof data === "string" ) {

			// Make sure leading/trailing whitespace is removed (IE can't handle it)
			data = jQuery.trim( data );

			if ( 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 ) {
		var xml, tmp;
		if ( !data || typeof data !== "string" ) {
			return null;
		}
		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 && jQuery.trim( 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 );
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
	},

	// args is for internal usage only
	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 ( ; i < length; i++ ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			} else {
				for ( i in obj ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			}
		}

		return obj;
	},

	// Use native String.trim function wherever possible
	trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
		function( text ) {
			return text == null ?
				"" :
				core_trim.call( text );
		} :

		// Otherwise use our own trimming functionality
		function( text ) {
			return text == null ?
				"" :
				( text + "" ).replace( rtrim, "" );
		},

	// results is for internal usage only
	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;
	},

	inArray: function( elem, arr, i ) {
		var len;

		if ( arr ) {
			if ( core_indexOf ) {
				return core_indexOf.call( arr, elem, i );
			}

			len = arr.length;
			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

			for ( ; i < len; i++ ) {
				// Skip accessing in sparse arrays
				if ( i in arr && arr[ i ] === elem ) {
					return i;
				}
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		var l = second.length,
			i = first.length,
			j = 0;

		if ( typeof l === "number" ) {
			for ( ; 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 ) {
		var retVal,
			ret = [],
			i = 0,
			length = elems.length;
		inv = !!inv;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( ; 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,
			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 ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}
		}

		// Flatten any nested arrays
		return core_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 ) {
		var args, proxy, tmp;

		if ( typeof context === "string" ) {
			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
		args = core_slice.call( arguments, 2 );
		proxy = function() {
			return fn.apply( context || this, args.concat( core_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 || jQuery.guid++;

		return proxy;
	},

	// Multifunctional method to get and set values of a collection
	// The value/s can optionally be executed if it's a function
	access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
		var i = 0,
			length = elems.length,
			bulk = key == null;

		// Sets many values
		if ( jQuery.type( key ) === "object" ) {
			chainable = true;
			for ( i in key ) {
				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
			}

		// Sets one value
		} else if ( value !== undefined ) {
			chainable = true;

			if ( !jQuery.isFunction( value ) ) {
				raw = true;
			}

			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 );
					};
				}
			}

			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: function() {
		return ( new Date() ).getTime();
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations.
	// Note: this method belongs to the css module but it's needed here for the support module.
	// If support gets modularized, this method should be moved back to the css module.
	swap: function( elem, options, callback, args ) {
		var ret, name,
			old = {};

		// Remember the old values, and insert the new ones
		for ( name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		ret = callback.apply( elem, args || [] );

		// Revert the old values
		for ( name in options ) {
			elem.style[ name ] = old[ name ];
		}

		return ret;
	}
});

修改了jQuery.expando的实现,在原来单纯地取当前时间的基础上,添加了一个随机数:

expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),

这样保证在同一时间,引入多个jQuery副本,这几个副本之间的expando不会相互冲突,导致元素上的data变得错乱。一般来说,是不会引入多个jQuery副本的,但是使用SealJS等的时候,配置不当的话,也是很容易出现此类问题的。

noConflict: function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}


if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}


return jQuery;
},

上面的方法的作用就是可以用jQuery代替$,避免冲突比如prototype.js也是用$来表示的。

下面一段是转载来的:

jQuery.holdReady()

Description: Holds or releases the execution of jQuery's readyevent.

描述:锁定或者释放jQuery的完成事件。

version added:1.6jQuery.holdReady( hold )

1.6版本的jQuery加入该函数

 

jQuery.holdReady(hold) whether the ready hold is being requestedor released

The $.holdReady() method allows the caller to delay jQuery'sready event. This advanced feature would typically be used by dynamic scriptloaders that want to load additional JavaScript such as jQuery plugins beforeallowing the ready event to occur, even though the DOM may be ready. Thismethod must be called early in the document, such as in the <head>immediately after the jQuery script tag. Calling this method after the readyevent has already fired will have no effect.

To delay the ready event, first call $.holdReady(true). When theready event should be released to execute, call $.holdReady(false). Note thatmultiple holds can be put on the ready event, one for each $.holdReady(true)call. The ready event will not actually fire until all holds have been releasedwith a corresponding number of $.holdReady(false) calls and the normal documentready conditions are met. (Seeready for more information.)

 

jQuery.holdReady(hold) hold表示完成事件的状态(被锁定或释放) $.holdReady()方法允许jQuery的完成事件被该函数锁定。这个高级特性的典型应用场合是动态载入脚本,比如jQuery插件等。在附加的脚本载入完成前,即使页面已经准备好,jQuery的完成事件也不会被触发。这个函数必须在页面的靠前部分被调用,比如在<head>标签当中,jQuery载入下一行。在完成事件被触发后调用此函数没有任何效果。使用方法:首先调用$.holdReady(true)[调用后完成事件将被锁定]。当准备好触发完成事件时,调用$.holdReady(false)。需要注意的是,可以对完成事件添加多个锁定,每个锁定对应一次$.holdReady(false)[解锁]调用。jQuery的完成事件将在所有的锁定都被解除,并且页面也已经准备好的情况下被触发。

Example:

Delay the ready event until acustom plugin has loaded.

例子:锁定完成事件直到用户脚本[myplugin.js]载入完成

$.holdReady(true); $.getScript("myplugin.js", function() {      $.holdReady(false); });

以上是现成度娘来的资料,以下详细解释一些其他的试验代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"  ></script>
    <script type="text/javascript">
        $(function () { alert($("#div_test").html()); })
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div id="div_test">
      this is a test!
    </div>
    </form>
</body>
</html>

 

该代码的运行结果是 跳出this is a test! 正常运行,现在讲代码改如下:

<script type="text/javascript">
        $.holdReady(true);
        $(function () { alert($("#div_test").html()); })
    </script>

代码将不会跳出弹出窗口。因为$.holdReady(true);锁定了Jquery对象。再后面加上$.holdReady(false);释放代码就恢复正常。

 

<script type="text/javascript">
        $.holdReady(true);
        $(function () { alert($("#div_test").html()); })
        $.holdReady(false);
    </script>
// Handle when the DOM is ready
ready: function( wait ) {


// Abort if there are pending holds or we're already ready
if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
return;
}


// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( !document.body ) {
return setTimeout( jQuery.ready );
}


// 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.resolveWith( document, [ jQuery ] );


// Trigger any bound ready events
if ( jQuery.fn.trigger ) {
jQuery( document ).trigger("ready").off("ready");
}
},

上面这段代码的意思是检查文档对象直到它能够允许被操作,这样做比 window.onload() 函数要快的多,因为只要文档对象载入完成就能够执行代码了,而不需要等待页面中的图片下载是否已经完成,这正是我们想要的。之所以用这个来取代 window.onload,就是因为它是在 dom 模型加载完成后就执行,而 window.onload 是在 dom 元素加载完全后才执行。

isFunction:判断是否为function

isArray:判断是否为数组

isWindow:用于测试是否为windows对象

isNumeric:检查传进去的参数是否是数字或者可否转换成数字

type:用来获取javascript数据类型[[class]]的对象

isPlainObject:用于测试是否为纯粹的对象

isEmptyObject:检查是否为空对象

error:接受一个字符串,并抛出包含这个字符串的异常。

parseHTML:将字符串解析到一个DOM节点的数组中。

parseJSON:接受一个标准格式的 JSON 字符串,并返回解析后的 JavaScript 对象。

parseXML:解析一个字符串到一个XML文档。

noop:空函数。

globalEval:在全局上下文下执行一些JavaScript代码。

camelCase函数的功能就是将形如background-color转化为驼峰表示法:backgroundColor。 此函数在jQuery的data函数,以及涉及到css的诸多函数中都有用到。

proxy:接受一个函数,然后返回一个新函数,并且这个新函数始终保持了特定的上下文语境。

下面是转载

access: function(elems, key, value, exec, fn, pass) { 
        var length = elems.length; 

        // Setting many attributes 
        if (typeof key === "object") { 
                for (var k in key) { 
                        jQuery.access(elems, k, key[k], exec, fn, value); 
                } 
                return elems; 
        } 

        // Setting one attribute 
        if (value !== undefined) { 
                // Optionally, function values get executed if exec is true 
                exec = !pass && exec && jQuery.isFunction(value); 

                for (var i = 0; i < length; i++) { 
                        fn(elems[i], key, exec ? value.call(elems[i], i, fn(elems[i], key)) : value, pass); 
                } 

                return elems; 
        } 

        // Getting an attribute 
        return length ? fn(elems[0], key) : undefined; 
}

access函数只在jquery对象的attr和css方法中用到。对于传入的多种形式的参数,起到为这2个函数统一参数的作用。 

access函数包含6个参数, 

elems: 元素的集合[collection],[类]数组, 
  
key: 属性名称,在key值的类型为object时,会拆解value成key,value形式再次执行jQuery.access 

value: 属性值, 

exec: 在属性值的类型为function时是[exec为true]否对设置之前的value值执行函数,在jquery源码中,这个值一直为true,因此我在想是否可能会有插件也利用这个函数,否则这个参数可以默认为true即可以省略掉, 

fn: 设[set]取[get]值的函数,包含3个参数或一个pass参数,在对于value是否传值的情况必须有不同处理,value不传值时必须有确定的返回值。例如fn.css里的: 
function(elem, name, value) { 
                return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name); 
}

pass: 是[pass为true]否设置成jquery对象的属性,例如(html,'str'),可以直接是<div html='str'>或<div>str</div>。这个pass值仅在使用使用attr方法,并且以attr(obejct,true)的形式时pass才为true。例如 
$('div').attr({ 
                click: function() {}, 
                html: "abc" 
}

true)相当于 
$('div').click(function() {}).html("abc")

实际上只在jQuery(html, props)[提供原始 HTML 标记字符串,动态创建由 jQuery 对象包装的 DOM 元素。同时设置一系列的属性、事件等的情况下]使用: 

$("<div>", { 
                "class": "test", 
                text: "Click me!", 
                click: function() { 
                                $(this).toggleClass("test"); 
                } 
}).appendTo("body");

该函数的返回值:在为value !== undefined时返回elems,实现链式操作。


now:返回一个数字,表示当前时间。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值