我们知道在 JavaScript 中有五种基本类型和对象(Object
)。这五种基本类型是 Number, String, Boolean, null, undefined
。
在 JavaScript 中,变量是没有类型的,或者说变量的类型是根据它的值动态变化的。所以在 JavaScript 中有一种检测变量数据类型的操作符,即 typeof
。
一般情况下,typeof
都能正确检测出变量的数据类型,比如:
typeof 1 === 'number';
typeof '1' === 'string';
typeof true === 'boolean';
typeof undefined === 'undefined';
typeof {a: 1} === 'object';
上面的5条语句都会返回 true
。
但是,请注意,上面并没有用 typeof
检测 null
的数据类型。
typeof null === 'null'; // false
typeof null === 'object'; // true
我们会看到这又是一个 JavaScript 的缺陷!
那么,如何检测一个变量是 ‘null’ 还是 ‘object’ 呢?
检测 null
要检测一个类型的类型,就要把握住这个类型特有的特点。
null
在基本数据类型中是一个假值。
console.log(!null); // true
// 但是 undefined 也是一个假值
console.log(!undefined); // true
利用 null
的这两个特点就可以检测 null
的数据类型:
var a = null;
if(!a && typeof a === 'object'){
console.log('a is null');
}
检测 object
有了上面检测 null
的经历,那么检测 object
就很容易理解了,就是需要同时排除 null
的情况。
var a = {key:1};
if( (a !== null) && (typeof a === 'object') ){
console.log('a is object');
}
我们这里显式地将 a
声明为一个对象,但是如果 a
被声明为函数或者数组呢?上面的检测方法还有效吗?
所以,如果要把检测 object
这个问题说清楚,就还得知道另外两种特殊的“对象类型”,即函数和数组。
var foo = function(){ return 1; }
var arr = [1];
console.log(typeof foo); // 'function'
console.log(typeof arr); // 'object'
好,现在我们来回答这个问题,如果当 a
被声明为函数,那么 (a !== null) && (typeof a === 'object')
将不能检测出 a
是对象。
所以还得继续改进检测方法。
我们得包含 a
被定义为函数这种情况。
所以,将检测方法改进为: (a !== null) && ( (typeof a === 'object') || (typeof a === 'function') )
。
这个方面对所有的对象(包括函数和数组)都能返回 true
。
拓展
现在,如果说我们要把数组排除在外,又应该如何改进我们的检测方法?
console.log((a !== null) && (typeof a === 'object') && (toString.call(a) !== '[object Array]'))
欢迎访问 Leo’s Blog