首页 > 代码库 > JQuery源码解析-JQuery的工具方法(2)
JQuery源码解析-JQuery的工具方法(2)
这篇对下面的方法进行讲解:
isFunction():是否为函数
isArray():是否为数组
isWindow():是否为window
isNumeric()是否为数字
type():判断数据类型
isPlainObject():是否为对象自变量
isEmptyObject():是否为空的对象
isFunction方法:
这个方法很简单,判断对象是否为函数,返回bool类型,看一下源码:
// 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"; },
源码很简单,通过调用jQuery.type方法判断返回值是否为function,这里需要注意的是注释部分,注释上说在IE老的版本浏览器中,从1.3以后就对DOM的方法和原生的方法不在支持了,这时返回的是false。
isArray方法:
isArray: Array.isArray,
可以看到这里直接用原生数组的方法,这也是因为原生的方法速度会比较快,所以有原生方法还是最后用原生的方法。
isWindow方法:
isWindow: function( obj ) { return obj != null && obj === obj.window; },
这个方法用来判断是否为window对象,这里用到了两个条件,先来看第一个:
obj != null,和null进行比较,只有null和undefined比较才会为真,所以这里先对这两种情况进行判断,以免后面的条件报错。
obj === obj.window 如果是window对象的话,其实下面的属性还会有个window属性,并且可以一直无限的调用例如: window.window.window.window..
这里先不说具体原因,等到以后在进行说明。
isNumeric方法:
isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); },
这个方法用来判断是否为number类型,那么这里为什么这么麻烦,而不是直接用typeof方法判断呢,是因为:
console.log(typeof NaN); //number
可以看到,用typeof方法判断NaN的时候返回也是number,所以为了可靠,不能使用原生的方法。
第一个条件中,先对参数进行转换,如果可以的话,那也就是为number类型,如果转换不了,返回的是NaN,也就不满足条件了。
第二个条件用了一个isFinite方法,这个方法是用来判断数字是否在可用范围内,因为计算机计算的数据有限,有时可能传入一个很大的数字,超出了计算机的运算范围,这里也返回false。
console.log(isFinite(Number.MAX_VALUE+Number.MAX_VALUE)); //false
type方法:
type方法返回的是传入参数的数据类型,如:
function a(){}; console.log($.type(a)); //function
源码:
type: function( obj ) { if ( obj == null ) { return String( obj ); } // Support: Safari <= 5.1 (functionish RegExp) return typeof obj === "object" || typeof obj === "function" ? class2type[ core_toString.call(obj) ] || "object" : typeof obj; },
首先对传入的参数进行判断,如果为null或undefined,直接返回这两种类型的字符串。
接下来判断参数是否为object或者function,如果是,则运行class2type[ core_toString.call(obj) ] || "object" ,否则直接返回 typeof obj就可以了,因为这种情况只能是基本类型,用typeof判断就足够了。
下面详细介绍这里最重要的一句:
class2type[ core_toString.call(obj) ] || "object"
core_toString对象其实就是{}.toString方法。在源码56行:
core_toString = class2type.toString,
可以找到,下面介绍一下这个tostring方法:
var arr=new Array(); console.log({}.toString.call(arr)); //[object Array]
这个方法还可以对date、function等进行判断,我们可以知道,如果用原生的方法,例如date类型,那返回的是object,如:
var arr=new Array();console.log(typeof arr); //object
所以最好使用这种情况进行类型的判断,这种判断是相当准确的。
下面在看一下class2type这个对象中保存了什么:
// Populate the class2type mapjQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase();});
可以看到,这个方法把所有类型都放到了这个对象里,然后拼好 [object +name] 对应的属性名和简写的值,那以后直接就可以通过属性名找出对应简写的数据类型了。
isPlainObject方法:
这个方法是判断是否为对象自变量的。返回bool值,源码:
isPlainObject: function( obj ) { // Not plain objects: // - Any object or value whose internal [[Class]] property is not "[object Object]" // - DOM nodes // - window if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } // Support: Firefox <20 // The try/catch suppresses exceptions thrown when attempting to access // the "constructor" property of certain host objects, ie. |window.location| // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 try { if ( obj.constructor && !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { return false; } } catch ( e ) { return false; } // If the function hasn‘t returned already, we‘re confident that // |obj| is a plain object, created by {} or constructed with new Object return true; },
第一个条件:
if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; }
这里先进行判断,如果不是obj类型,或者是节点类型,也或者是window对象,那么直接返回false。
// Support: Firefox <20 // The try/catch suppresses exceptions thrown when attempting to access // the "constructor" property of certain host objects, ie. |window.location| // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 try { if ( obj.constructor && !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { return false; } } catch ( e ) { return false; }
这里对另一种情况进行判断,有一种特殊的情况就是传入window.location的时候,因为上面的判断语句无法对这种情况进行判断。
首先判断这个对象是否有constructor,如果有,在判断其原型上是否有isPrototypeOf方法,如果没有,那么则返回false,core_hasOwn:
core_hasOwn = class2type.hasOwnProperty,
从这里可以看到这里之前调用object的hasOwnProperty方法。
这段代码为什么要用try呢,注释中的说明是因为在火狐20一下的版本中,如果多次调用window.location.contructor时,可能会出现too much recursion 这个错误,具体原因请看:https://bugzilla.mozilla.org/show_bug.cgi?id=814622
isEmptyObject方法:
这个方法用来判断是否为空对象。
isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; },
这里看如直接用for in 方法来处理,如果对象内有属性,则会被 for in到,返回false。另外for in方法只会对自己添加属性进行遍历,而不会对自带属性遍历。
JQuery源码解析-JQuery的工具方法(2)