Wenzi

jQuery中的工具方法$.isFunction, $.isArray(), $.isWindow()

蚊子前端博客
发布于 2015/07/25 06:00
jQuery除了提供$.type方法外,还提供了几个其他的工具方法,如$.isFunction, $.isArray(), $.isWindow, $.isNumeric等

javascript 中对变量类型的判断中,我们讲解了了 jQuery 中$.type()实现的原理。当然,jQuery 除了提供$.type的工具方法外,还提供了几个其他的工具方法:$.isFunction(), $.isArray(), $.isWindow(), $.isNumeric()等。这几个方法从方法名上就能看出其用途来,下面我们来一一讲解这几个方法在 jQuery(2.1.2)中实现的内部细节。

1. $.isFunction() #

$.isFunction()是用来判断变量是否为 function 类型,我们通过几个例子来看看:

$.isFunction(123); // false
$.isFunction(true); // false
$.isFunction([1, 2]); // false
$.isFunction(function () {}); // true

function func() {}
var sfunc = function () {};
$.isFunction(func); // true
$.isFunction(sfunc); // true

从上面的例子中能够看到,在$.isFunction(param)中,若传入的 param 是 function 类型,则返回 true;其他的类型则返回 false。

查看 jQuery 的源码我们可以看到,$.isFunction()也是通过$.type()实现的:

isFunction: function( obj ) {
	return jQuery.type(obj) === "function";
}

2. $.isArray() #

$.isArray()是用来判断变量是否为 array 类型。同样,我们也通过几个例子来看看$.isArray 的用法:

$.isArray(123); // false
$.isArray(true); // false
$.isArray([1, 2]); // true
$.isArray(new Array(3, 4)); // true

无论是 array 的字面量还是使用new关键词创建的变量,都能使用$.isArray()判断其是 array 类型。在 jQuery 源码中,$.isArray 调用的就是原生 Array 提供的 isArray 方法。因为在高版本的浏览器中,已经给原生 JavaScript 提供了一个isArray方法用来判断变量是否为 array 类型。

isArray: Array.isArray;

3. $.isWindow() #

$.isWindow()是用来判断当前变量是否为window,如:

$.isWindow(window); // true
$.isWindow([]); // false
$.isWindow(null); // false

在 jQuery 源码中:

isWindow: function( obj ) {
	return obj != null && obj === obj.window;
}

他是通过判断 obj 是否有 window 属性,来判断 obj 是否为 window 对象。因为 window 对象里有一个属性 window,就是他自己,因此:window.window===window,同样的:

window.window.window.window === window;

可以一直循环下去。

而代码里为什么要先判断一下 obj 是否为 null 呢?因为在判断 null 或 undefined 是否有 window 属性时,代码会抛出异常:Uncaught TypeError: Cannot read property 'window' of null。因此,为了防止代码错误,首先判断变量是否为 null,若为 null,则它肯定不是 window 对象,直接返回 false;否则再判断这个变量有没有 window 属性。

4. $.isNumeric() #

$.isNumeric()是用来判断当前变量是否为数字类型,可是为什么我不使用$.type()=="number"来判断呢。我们先来看几个官方的例子:

$.isNumeric('-10'); // true
$.isNumeric(16); // true
$.isNumeric(0xff); // true
$.isNumeric('0xFF'); // true
$.isNumeric('8e5'); // true (exponential notation string)
$.isNumeric(3.1415); // true
$.isNumeric(+10); // true
$.isNumeric(0144); // true (octal integer literal)
$.isNumeric(''); // false
$.isNumeric({}); // false (empty object)
$.isNumeric(NaN); // false
$.isNumeric(null); // false
$.isNumeric(true); // false
$.isNumeric(Infinity); // false
$.isNumeric(undefined); // false

使用$.isNumeric()能够判断出**"-10"**, **"0xFF"**这样字符串类型的数字,而$.type()则会将其解析为 string 类型。

在 jQuery 源码中,是这样判断变量类型的:

isNumeric: function( obj ) {
	// parseFloat NaNs numeric-cast false positives (null|true|false|"")
	// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
	// subtraction forces infinities to NaN
	// adding 1 corrects loss of precision from parseFloat (#15100)
	return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
}

首先判断其变量是否为 array 类型,若是则直接返回 false。可是为什么要先判断变量是否为 array 类型呢?因为**[123]**这样类型的数组是可以直接进行减法运算的,同时也能通过 parseFloat(["123"])转换为数字:

[100] -
  (60)[100] - // 40
  [60]; // 40
parseFloat([123]); // 123
parseFloat(['345']); // 345

因此不能直接通过 parseFloat()转换,然后判断。首先得判断这个变量是否为数组;若不是才进行下一步的判断:

obj - parseFloat(obj) + 1 >= 0;

纯数字,字符串类型的数字,0 开头的数字(8 进制),0x 开头的数组(16 进制)等,都能通过 parseFloat()正常进行转换为 10 进制的数字。经过上面表达式的运算,肯定是大于 0 的。可是为什么要加上 1 呢?代码里也解释了,通过 parseFloat()转换到,会造成精度丢失的问题,因此+1 后,运算结果更加的准确。

而其他类型的通过 parseFloat()转换后得到的是NaN,NaN 无论通过怎样的运算,都是不能跟 0 比较的,返回 false。

在 jQuery 之前的版本(如 2.0.2)中:

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

我们可以发现,使用这样的代码$.isNumeric([123])运行后,得到的 true,而实际上,它是个数组类型。不过还好,在后续的版本已经修复了。

5. $.isEmptyObject() #

$.isEmptyObject()不是用来判断变量的类型了,而是判断一个 object 类型是否为空,不包含任何属性。

从 jQuery 1.4 开始,这个方法既检测对象本身的属性,也检测从原型继承的属性(因此没有使用 hasOwnProperty)。参数应当是一个普通的 JavaScript 对象, 对于其他类型的对象(DOM 元素,原始 strings/numbers,host 对象)在跨浏览器中可能无法提供一致的结果。

$.isEmptyObject({ name: 'wenzi' }); // false
$.isEmptyObject({}); // true

function Person() {
  this.name = 'wenzi';
}
$.isEmptyObject(new Person()); // false

function Student() {}
Student.prototype.name = 'wenzi';
$.isEmptyObject(new Student()); // false

我们能够看到,不论是对象本身的属性,还是 prototype 上的属性,只要存在,都会返回 false。

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

在 jQuery 中,是通过for~in进行检测的。因为 for~in 也是能循环到 prototype 上的属性的,若进入到循环中,则说明 obj 存在属性,发挥 false;否则返回 true。

6. 总结 #

jQuery 中还提供了很多各种各样的工具方法,让我们在编写 js 代码时更加的方便。以后有机会时再总结其他的工具方法。

Simple Empty
No data