精华 JavaScript类型检测
发布于 4 年前 作者 dandananddada 6000 次浏览 最后一次编辑是 3 年前 来自 分享

写在前面

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

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
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]"
回到顶部