JavaScript内置的类型检测机制并非完全可靠。事实上,发生错误否定及错误肯定的情况也不在少数。比如说 typeof 操作符吧,由于它有一些无法预知的行为,经常会导致检测数据类型时得到不靠谱的结果。(如typeof检测一个不存在的变会返回undefined)
再比如, instanceof 操作符在存在多个全局作用域(像一个页面包含多个框架)的情况下,也是问题多多。
var isArray = value instanceof Array;
以上代码要返回 true , value 必须是一个数组,而且还必须与 Array 构造函数在同个全局作用域中。(别忘了, Array 是 window 的属性。)如果 value 是在另个框架中定义的数组,那么以上代码就会返回 false 。
解决上述问题的办法都一样。大家知道,在任何值上调用 Object 原生的 toString()方法,都会返回一个 [object NativeConstructorName] 格式的字符串。每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。举个例子吧。
alert(Object.prototype.toString.call(value)); //”[object Array]”
由于原生数组的构造函数名与全局作用域无关,因此使用 toString() 就能保证返回一致的值。利用这一点,可以创建如下函数:
function isArray(value){
return Object.prototype.toString.call(value) == ”[object Array]”;
}
同样,也可以基于这一思路来测试某个值是不是原生函数或正则表达式:
function isFunction(value){
return Object.prototype.toString.call(value) == ”[object Function]”;
}
function isRegExp(value){
return Object.prototype.toString.call(value) == ”[object RegExp]”;
}
Object 的 toString() 方法不能检测非原生构造函数的构造函数名。因此,开发人员定义的任何构造函数都将返回[objectObject]。有些JavaScript库会包含与下面类似的代码。
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON) ==
“[object JSON]”;
在Web开发中能够区分原生与非原生JavaScript对象非常重要。只有这样才能确切知道某个对象到底有哪些功能。这个技巧可以对任何对象给出正确的结论。