jQuery 1.6 源码学习(七)——core.js[7]之实用工具方法(Utilities)

jQuery中提供/封装了许多工具类的方法,个人认为比较重要的有:

parseJSON方法:

	parseJSON: function( data ) {
		//只处理字符串数据
		if ( typeof data !== "string" || !data ) {
			return null;
		}

		// Make sure leading/trailing whitespace is removed (IE can't handle it)
		data = jQuery.trim( data );
		// 优先使用本地方法处理,很多现代浏览器中提供了JSON对象用于处理JSON(比如chrome)
		// 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 eval("("+data+")");
			//但是这样写能防止变量污染
			//更多的功效是提供一些编译优化以及工具验证
			//参见 http://stackoverflow.com/questions/2449220/jquery-uses-new-functionreturn-data-instead-of-evaldata-to-parse-j
			return (new Function( "return " + data ))();

		}
		//error方法的实现十分简单,抛出一个msg就完了
		jQuery.error( "Invalid JSON: " + data );
	}, 

parseXML方法:

	// parseXML 几乎没什么好说的。就是简单地调用内置对象来解析XML。
	// Cross-browser xml parsing
	// (xml & tmp used internally)
	parseXML: function( data , xml , tmp ) {
		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 );
		}

		tmp = xml.documentElement;

		if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
			jQuery.error( "Invalid XML: " + data );
		}

		return xml;
	}, 

globalEval方法:

	//该方法作用域为全局环境,一般用来加载外部脚本
	globalEval: function( data ) {
		if ( data && rnotwhite.test( data ) ) {
			// execScript 为IE专有,其执行环境为global
			// 更多参见 http://www.cnblogs.com/snandy/archive/2011/03/16/1986055.html
			// 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 );
		}
	}, 

proxy方法:

	//在文档中可以清晰看到proxy支持两种调用方式:
	//jQuery.proxy( function, context ) 和 jQuery.proxy( context, name )
	proxy: function( fn, context ) {
		if ( typeof context === "string" ) { //这里对应jQuery.proxy( context, name )
			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 ) ) );
			};
		// 为原始函数设置guid,以便我们可以移除用proxy绑定的事件。
		// 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;
	}, 

可能最后一个guid不太容易理解其用意,我们用下面一个简单的示例来说明:

	var obj = {
		name : 'obj',
		method : function (){
			alert(this.name);
		}
	}
	$("input#btn").click($.proxy(obj.method,window)).unbind('click',obj.method); 

此时unbind是可以取消obj.method的绑定的,至于其具体实现,留至看事件处理代码时再做分析。

其他还有一些方法诸如trim,noop,inArray等的实现就比较简单了,在此就不一一分析了,源码中应该是一眼就能看明白的,至此,core.js的分析告一段落。

原文地址:https://www.cnblogs.com/firstdream/p/2342755.html