精华
JavaScript类型检测
写在前面
今天在看项目代码的时候有一段类型检测,写法比较绕:
var nativeToString = Object.prototype.toString;
function isObject(input) {
return nativeToString.apply(input).indexOf('Object') > -1;
}
出于好奇搜了下相关的内容,把了解到的东西贴出来分享下。 参考文章:转 JavaScript中判断对象类型的种种方法。
JavaScript类型检测
JavaScript中检测对象类型的运算符主要有三种:typeof、instanceof和对象的constructor属性。
typeof
typeof用于区分对象和原始类型,对于Date、RegExp等类型返回结果都是"object"
var number = 11
, string = "string"
, obj = {}
, array = new Array()
, date = new Date();
console.log(typeof number); //=>number
console.log(typeof string); //=>string
console.log(typeof obj); //=>object
console.log(typeof array); //=>object
console.log(typeof date); //=>object
instanceof
instanceof用来判断具体对象类型,是二元操作符,返回true
或false
。
var array = [];
console.log( array instanceof Array ); //=>true
console.log( array instanceof Object ); //=>true
console.log( array instanceof Date ); //=>false
constructor
constructor引用了初始化对象的构造函数,也可以用于判断具体的对象类型。但是和instanceof不同,对于Array、Date等对象类型与Object
不等价。
var array = [];
console.log( array.constructor == Array ); //=>true
console.log( array.constructor == Object ); //=>false
console.log( array.constructor == Date ); //=>false
cross-frame
不同的iframe中创建的数组不会共享prototype属性,就会导致instance和constructor就无法正确判断类型。
<script>
window.onload=function(){
var iframe_arr=new window.frames[0].Array;
alert(iframe_arr instanceof Array); //=> false
alert(iframe_arr.constructor == Array); //=> false
}
</script>
可以采用跨原型链调用toString()
方法解决上述问题。
var number = 11
, string = "string"
, obj = {}
, array = new Array()
, date = new Date();
console.log( Object.prototype.toString.call(number) ); //[object Number]
console.log( Object.prototype.toString.call(string) ); //[object String]
console.log( Object.prototype.toString.call(obj) ); //[object Object]
console.log( Object.prototype.toString.call(array) ); //[object Array]
console.log( Object.prototype.toString.call(date) ); //[object Date]
【附录】
获取对象类型名称
/**
* Returns internal [[Class]] property of an object
*
* Ecma-262, 15.2.4.2
* Object.prototype.toString( )
*
* When the toString method is called, the following steps are taken:
* 1. Get the [[Class]] property of this object.
* 2. Compute a string value by concatenating the three strings "[object ", Result (1), and "]".
* 3. Return Result (2).
*
* __getClass(5); // => "Number"
* __getClass({}); // => "Object"
* __getClass(/foo/); // => "RegExp"
* __getClass(''); // => "String"
* __getClass(true); // => "Boolean"
* __getClass([]); // => "Array"
* __getClass(undefined); // => "Window"
* __getClass(Element); // => "Constructor"
*
*/
function __getClass(object){
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
};
检测类型
var is = {
types: [
"Number"
, "Boolean"
, "String"
, "Object"
, "Array"
, "Date"
, "RegEpx"
, "Window"
, "HTMLDocument"
]
};
is.types.forEach(function(type){
is[type] = function(type){
return function(obj){
return Object.prototype.toString.call(obj) == "[object "+type+"]";
}
}(type);
});
console.log( is.String("String") ); //=>true
console.log( is.Boolean(false) ); //=>true
console.log( is.Number(12) ); //=>true
console.log( is.Array([]) ); //=>true
6 回复
js 的类型检测就是个坑,用了库的话还好。我用 lodash 的那套。
同用lodash
来检测
@alsotang 确实,刚刚又翻了翻其他代码,这个帖子给出的内容应该也不严谨,还要undefined这方面因素没有考虑到。
mark, 学习
function isObject(value) {
return value === Object(value);
}
Object.prototype.toString.call(window)
Chrome ==> "[object global]"
IE ==> "[object Window]"