javascript 安全的类型监测

1,217 阅读2分钟
原文链接: www.chengkangjian.com

数据类型检测

ECMAScript有五种简单的数据类型,分别为Undefined、Null、String、Number、Boolean,还有一个复杂的数据类型Object。ECMAScript的语言的动态性意味着我们可以使用以上6种数据类型表示任何数据。

因为数据类型是松散的,所以我们需要一些手段来准确的检测给定变量的数据类型。

typeof

tepeof是检测基本数据类型的好手,他有六种检测结果,分别是Undefined、Object、Function、String、Number、Boolean,所以它是判断一个变量是:未定义值、对象、函数、字符串、数值、布尔值的最佳工具。

typeof undefined  //"undefined"
typeof {}  //"object"
typeof function(){}  //"function"
typeof ''  //"string"
typeof 1  //"number"
typeof true  //"boolean"
typeof null  //"object"
typeof [] //"object"

从上面可以看出typeof虽然是检测基本数据类型的好手,但是在检测引用类型的数据时就力不从心了,下面会提到如何检测引用数据类型。另外还有个问题值得思考:

为什么null的检测类型是Object?

看书中对null的描述:

The value null represents the intentional absence of any object
value

首先,null是一个原始值。
关于 typeof null //"object" 的结果,从一开始出现JavaScript就是这样的。

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是0。由于 null 代表的是空指针(大多数平台下值为0x00),因此,null的类型标签也成为了0,typeof null就错误的返回了”object”.(referenc)

据说该问题在ECMAScript 6中提出typeof null === 'null'的讨论 (该提议已被否决)。

安全类型检测

javascript内置的类型检测机制并非完全可靠。比如typeof操作符,由于一些无法预知的行为,会得到不靠谱的结果。
instanceof存在于多个作用域的情况,通过下面的方式检测数组:

var isArray = value instanceof Array

以上代码若返回true,value必须是一个数组,而且必须与Array构造函数处于同一个作用域中。如果value是别的框架定义的数组,以上的代码又可能会返回false。

如何解决上述问题

上述解决的办法都一样,在任何值上调用Object原生的toString方法时,都会返回一个类似于[object NativeConstructorName]格式的字符串,比如:

Object.prototype.toString.call(['']) //"[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]";
}
function isNativeJSON(value) {  
  return window.JSON&&Object.prototype.toString.call(value) == "[object JSON]";
}

⚠需要注意的一点是,Object.prototype.toString()本身也会被修改,本文讨论的仅仅是该方法未被修改的情况下。