在js中我们通常判断类型通常用 typeof ;但是这种判断方法往往得不到具体的类,比如typeof []得到是object而不是
Array。
普通类型:
在underscore.js中使用的是 Object.prototype.toString.call(obj)来对一些普通类型进行判断。
Object.prototype.toString.call(obj)会返回obj所属的具体类型。如:Object.prototype.toString.call([])//返回
[object array]
代码如下
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol', 'Map', 'WeakM
ap',
'Set', 'WeakSet'], function(name) {
_['is' + name] = function(obj) {
return toString.call(obj) === '[object ' + name + ']';
};
});
然而Object.prototype.toString.call(obj)并不是全能的,在一些类型的检测上它存在兼容性问题,比如arguments ,
在IE<9的浏览器下会返回[object object],对于这样的问题 underscore.js 是同类型上所具有的特殊属性来进行判断
,比如arguments:
if (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
return _.has(obj, 'callee');
};
}
利用arguments的callee属性来解决IE<9下的兼容性问题。
特殊类型:
1、对于Array的类型检测,js中提供了原生的isArray函数,但存在兼容性问题,解决方法:
_.isArray = Array.isArray || function(obj) {
return toString.call(obj) === '[object Array]';
};
2、类数组
在underscore.js中对于类数组的检测使用的是鸭子模型
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;//代表的是js最大精确整数
var isArrayLike = function(collection){
var length = getLength(collection);
return typeof length == 'number' && length > 0 && length < MAX_ARRAY_INDEX;
};
3、undefined
_.isUndefined = function(obj){
return obj === void 0;//void运算符计算次算表达式返回undefined
};
4、Boolean
_.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
};
个人感觉isBoolean的分支检测是为了性能的优化。
5、NaN
_.isNaN = function(obj){
return _.isNumber(obj) && isNaN(obj);
};
NaN类型用来代表不是Number类型,但它本身是Number类型,而且NaN不等于NaN,isNaN用来检测是不是NaN,也就是不是
数。
6、Object
_.isObject = function(obj){
var type = typeof obj; //首先检查参数类型
return type === 'function' || type === "object" && !!obj; //返回布尔值
};
7、DOM元素
_.isElement = function(obj){
return !!(obj && obj.nodeType === 1);
};
只说一点typeof检测函数类型返回function,但function是属于Object的一个子类。
最后:到这里大致的类型检测就介绍完毕了,当然,underscore 还有很多其他的有用的工具类判断方法,具体可以去
看源码 。