JS 类型检测方法
简介
javascript的变量类型分为原始类型和引用类型。
- 原始类型有6种, 注意多了 Symbol
- Number
- String
- Boolean
- Null
- Undefined
- Symbol
- 引用类型包括
- Function
- Array
- Date
- Object
- RegExp
而检测这些类型的变量有3种办法:typeof
,instanceof
,Object.prototype.toString.call
。让我来一一例举,废话不多说,上代码。
//首先是typeof
var obj = 1;
typeof obj; //"number"
obj = "abc"
typeof obj; //"string"
obj = false
typeof obj; //"boolean"
obj = undefined;
typeof obj; //"undefined"
obj = null;
typeof obj; //"object",WTF,其实这是js的一个bug,人艰不拆 T_T
obj = Symbol();
typeof obj; //"symbol"
obj = function(){};
typeof obj; //"function"
obj = [];
typeof obj; //"object"
obj = {};
typeof obj; //"object"
obj = /w/g;
typeof obj //"object"
从上面我们可以得出type能检测原始类型number
,string
,boolean
,undefined
,引用类型的function
。但是对于数组和对象却是无法区分。
而关于引用类型,还可以尝试下instanceof
操作符。
var obj = function(){};
obj instanceof Function; //true
obj = [];
obj instanceof Array; //true
obj = {};
obj instanceof Object; //true
obj = new Date()
obj instanceof Date; //true
obj = /w/g;
obj instanceof RegExp; //true
//....wait for it, 事情其实还没完呢
obj = [];
obj instanceof Object; //true 所有引用类型其实都是继承自Object对象的,所以你懂的。
incetanceof 操作符能鉴别引用类型,可惜有个缺憾是,如果想鉴别一个变量object类型而不是其他的function
,array
,date
什么的,仍然需要花一番力气。
这里我们是不是漏了什么,如果..
var obj = new String('abc');
typeof obj; //"object" 。
obj instanceof String; //true 。
天了个撸,不能愉快玩耍了。要解释这个, 就得解释js里变量的赋值规则。
- 原始类型的变量直接保存原始值,而不是一个指向对象的指针。如果一个变量赋值给另一个变量,那么每个变量都它自己的一份数据拷贝,并不会相互影响。
- 引用类型的变量保存的是一个指向内存中实际对象所在的指针(或者说引用)。因此当你将一个对象赋值给变量时,实际是赋值给这个变量一个指针。意味着将一个变量赋值给另一个变量时,两个变量指向的是内存中同一个对象。
var obj = 'abc';
obj.something = 1;
var firstChar = obj.charAt(0); //"a"
console.log(obj.something); //undefined
//实际上js做了这样的处理
var obj = 'abc';
var temp = new String(obj);
var firstChar = temp.charAt(0); //"a"
temp.something = 1;
temp = null;
console.log(obj.something); //undefined
创建了一个临时的引用类型变量去访问属性,修改属性,然后就被释放了,扯远了。
总而言之,如果指定obj = "abc"
则obj保存的实际上就是abc的值,是一个基本类型。而如果指定obj = new String('abc')
那么obj实际上保存的是一个指向字符串对象的指针。所以就不难理解两者对于typeof
和instanceof
的差别了
额,读者:“说了这么多,你有没有一种万全的手段哇”。好吧, 我们来一个简单又粗暴的鉴别手段。
var obj = 1;
Object.prototype.toString.call(obj) === '[object Number]'; //true
obj = new Number(1);
Object.prototype.toString.call(obj) === '[object Number]'; //true
obj = Symbol();
Object.prototype.toString.call(obj) === '[object Symbol]'; //true
obj = [];
Object.prototype.toString.call(obj) === '[object Array]'; //true
obj = new Array();
Object.prototype.toString.call(obj) === '[object Array]'; //true
Object.prototype.toString.call(obj) === '[object Object]'; //false
这个方法是不是很好用呢, 哇哈哈哈哈。
总结归纳了下,我列举了一些校验函数:
//低版本ie中undefined变量可以被修改,所以使用void 0 获取真实的undefined值,
var isUndefined = function(obj) {
//or: return typeof obj === 'undefined';
return obj === void 0;
};
//typeof null 的结果是"object"。
var isNull = function(obj) {
return obj === null;
};
// boolean值,number值和string值需要考虑两种情况,值为字面量时使用typeof和Object.prototype.toString能检测;
// 值为构造函数构建的时候需要使用Object.prototype.toString或者instanceof检测
var isBoolean = function(obj) {
return Object.prototype.toString.call(obj) == '[object Boolean]';
};
var isNumber = function(obj) {
return Object.prototype.toString.call(obj) == '[object Number]';
};
var isString = function(obj) {
return Object.prototype.toString.call(obj) == '[object String]';
};
var isSymbol = function(obj) {
return Object.prototype.toString.call(obj) == '[object Symbol]';
};
var isNaN = function(obj) {
return obj !== obj;
};
//typeof 操作符在引用类型的变量里能对function有效。
var isFunction = function(obj) {
//or: return Object.prototype.toString.call(obj) == '[object Function]';
return typeof obj === 'function';
};
var isDate = function(obj) {
return Object.prototype.toString.call(obj) == '[object Date]';
}
var isArray = function(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
var isObject = function(obj) {
//or: return obj === Object(obj);
return Object.prototype.toString.call(obj) == '[object Object]';
}
var isRegExp = function(obj) {
//or: return obj === Object(obj);
return Object.prototype.toString.call(obj) == '[object RegExp]';
}
var has = function(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
};
//判断数组,字符串,对象是否为空
var isEmpty = function(obj) {
if (obj == null) return true;
if (isArray(obj) || isString(obj)) return obj.length === 0;
for (var key in obj) if (has(obj, key)) return false;
return true;
};
最后再来一个好用的识别方法
function getType(p) {
if (obj === void 0) {
return 'Undefined';
}
if (obj === null) {
return 'Null';
}
/function.(\w*)\(\)/.test(p.constructor); //通过其构造函数来获取对应的类型。
return RegExp.$1;
}
getType('1'); //"String"