这次分析的函数就是用extend添加到jQuery下的,这次分析将拆分成片段来讲,首先是最前面几个简单的变量和函数:
//保证当前页面上的每个jQuery都是独一无二的 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), isReady: true, //错误抛出函数 error: function( msg ) { throw new Error( msg ); }, noop: function() {},
接下来几个函数会涉及到jQuery的type函数和support中的ownLast,所以先讲解这两个的用处和原理(type就是在这段extend,只是提前分析了):
type: function( obj ) { if ( obj == null ) { return obj + ""; } //判断obj的类型,若是object或是function,则需要toString进行进一步检查,class2type = {};toString = class2type.toString; //class2type中保存了特定类型检测出的键值对 return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call(obj) ] || "object" : typeof obj; }
var i; for ( i in jQuery( support ) ) { break; } support.ownLast = i !== "0";
上面的一段程序就是为了生成ownLast的,support中保存了一些浏览器的怪异行为,ownLast就是其中之一。我们知道正常的for..in..循环,首先是从一个对象的实例属性开始的,然后再循环prototype中的属性。但是在IE9之前的版本中,这个刚好是反过来的。所以在这里,jQuery(support)返回的对象中,第一个i应该是0,但是在IE中的是‘andSelf‘,这是jQuery中prototype里的最后一个属性,所以最后用i与0比较,确定for..in..顺序。
接下来就是对那些函数的分析了:
//根据上面讲的type函数判断传入参数的具体类型 isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, //window.window == window isWindow: function( obj ) { return obj != null && obj == obj.window; }, isNumeric: function( obj ) { // parseFloat在对普通情况下非数字的判断很准确 // 但是当数字以进制的字母开头时,判断不准确,特别是十六进制时 // 同时infinite时,parseFloat返回NaN return obj - parseFloat( obj ) >= 0; }, isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; }, isPlainObject: function( obj ) { var key; //首先必须是一个对象 // 然后我们不能让nodeList等DOM通过这个检验 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try { // 没有constructor的对象肯定是个普通的对象 // 确定constructor可以再当前属性中,但是不应该有prototype中出现 // 确切来说就是可以有constructor,constructor指向的对象中可以有prototype属性 //但是其下面不能有isPrototypeOf if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 下会对特定的对象判断产生错误 return false; } // 支持IE<9的情况 // 就是处理那些首先循环继承来的属性而不是自身属性 if ( support.ownLast ) { for ( key in obj ) { return hasOwn.call( obj, key ); } } // 对于正常情况,首先循环的是自身属性 // 如果最后一个属性还会自身属性的话,那么所有的属性都是自身属性 for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }
globalEval: function( data ) { if ( data && jQuery.trim( data ) ) { // 在IE中使用 execScript // 我们通过call的方法,使得上下文环境变为window,与execScript统一 ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // 主要使用在css中 // 处理MicroSoft忘记在属性前加供应商名称 camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, //判断传入的element的nodeName和name是否相同 nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); },
先写这一部分,晚点再对后半部分写一篇上来,最近坑爹的天气,搞得直接就感冒了,头昏昏沉沉的。。。