underscore源码分析系列-3-对象方法简分析

前言

在前一篇文章中,我们主要说了underscore中几个很常见也很简单的api,在这篇博客中,我们希望说一下对象方面的api

underscore源码分析系列-3

_.isNull

判断一个对象是不是null,如果事就返回true。

1
2
3
_.isNull = function (obj) {
return obj === null;
}

注意判断用的事三等,也就是当你传入undefined 的时候,返回的事false。

_.isUndefined

判断传入的值是否事undefined

1
2
3
_.isUndefined = function (obj) {
return obj === void 0;
}

判断条件中用的是 void,其作用的起到计算表达式的作用,计算结束之后永远返回undefined,为什么这里要用到void这个特性呢? 本质上还是因为低版本的ie中undefined是可以被修改的。

_.isNaN

如果object 是 “不是一个数字”,则返回true。

注意: 这和原生的isNaN 函数不一样,如果变量是undefined,原生的isNaN 函数也会返回 true 。

1
2
3
_.isNaN = function (obj) {
return _.isNumber(obj) && obj !== +obj;
}

首先判断传入的值是否是Number类型,接着判断该值是否等于本身。重点看后面的判断条件 +obj,这句话可以将字符串的数字转化成真正的数字,便排除了isNaN这种情况。

_.isObject

如果object是一个对象,返回true。需要注意的是JavaScript数组和函数是对象,字符串和数字不是。

1
2
3
4
_.isObject = function (obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}

js的集中数据类型中包括常见的{},其实函数也看作是一种对象类型。当然null也称作是空对象。所以该api,将类型是function或者object(出了null)都返回true。

_.isElement

如果object是一个DOM元素,返回true。

1
2
3
_.isElement = function (obj) {
return !!(obj && obj.nodeType === 1);
}

通过传入对象的nodeType属性来判断一个对象是否是DOM元素,其实这样并不严谨。

1
2
3
4
5
6
var obj = {
name: 'qianlong',
nodeType: 1
};
console.log(_.isElement(obj)) => true;

可以看到只要对象有一个属性是nodeType并且是1,那么_.isElement就会认为这是一个DOM元素。

_.has(object, key)

判断object对象是否含有key属性。 有则返回true,否则返回false

1
2
3
4
5
6
var ObjProto = Object.prototype;
var hasOwnProperty = ObjProto.hasOwnProperty;
_.has = function (obj, has) {
return obj != null && hasOwnProperty.call(obj, key);
}

注意这里通过hasOwnProperty判断,也就是原形是上面的属性,不会去判断。

1
2
3
4
5
6
7
8
9
10
var Person = function(name){
this.name = name;
};
Person.prototype.sex = 'boy';
var p1 = new Person('qianlong');
_.has(p1, 'name'); // true
_.has(p1, 'sex'); // false

_.isArray

判断传入的值是否是数组,如果是就返回true

判断一个变量是否是数组,想必大家比较熟悉了,我们看下_中是怎么实现的

1
2
3
4
5
6
7
var ObjProto = Object.prototype;
var toString = ObjProto.toString;
var nativeIsArray = Array.isArray;
_.isArray = nativeIsArray || function (obj) {
return toString.call(obj) === '[object Array]';
}

首先在源码的开头保存了nativeIsArray,如果在支持该函数的浏览器中就用这个,如果在一些版本较低的浏览器中就用自己实现的。很显然其他的数据类型也可以用类似的方法来实现。

.isArguments, .isFunction ,.isString, .isNumber, .isDate, .isRegExp, _.isError

1
2
3
4
5
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
_['is' + name] = function(obj) {
return toString.call(obj) === '[object ' + name + ']';
};
});

这里用到了其自身的工具方法_.each来对一个数组进行遍历,最后导出多个相应的判断数据类型的方法。