精华 JavaScript类型检测
发布于 3天前 作者 dandananddada 311 次浏览 来自 分享

写在前面

今天在看项目代码的时候有一段类型检测,写法比较绕:

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用来判断具体对象类型,是二元操作符,返回truefalse

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
3 回复

js 的类型检测就是个坑,用了库的话还好。我用 lodash 的那套。

同用lodash来检测

@alsotang 确实,刚刚又翻了翻其他代码,这个帖子给出的内容应该也不严谨,还要undefined这方面因素没有考虑到。

回到顶部