前言
在我们编写js的代码中,要处理各种数据。ECMAScript中有5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number和String,还有1种复杂数据类型——Object。
面对这6种数据类型,我们应该如何做出准确的判断呢?
typeof运算符
typeof可以解决大部分的数据类型判断,它是一个一元运算,放在一个运算值之前,其返回值为一个字符串。
以下是各种数据类型返回结果:
var iStr = "JavaScript"; |
从中我们能够发现:
null、对象和数组都会返回"object"- 可以使用
typeof区分null和undefined - 函数会返回
"function" - 暂时无法区分出对象和数组
在IE8和更早版本的IE浏览器中,使用typeof来检测DOM节点(比如document.getElementById())中的函数都返回"object"。// IE8及以下
typeof document.getElementById; // "object"
typeof document.getElementsByTagName; // "object"
typeof document.createElement; // "object"
instanceof运算符
instanceof运算符希望左操作数是一个对象,右操作数标识对象的类。如果左侧的对象是右侧类的实例,则表达式返回true,否则返回false。
|
使用instanceof,我们可以区分出对象和数组。
instanceof是基于实例与类的关系来判断类型的,如果一个页面中有多个<iframe>,每个<iframe>下的Object、Array、String等基类都是不同的对象,所以instanceof不能跨<iframe>。
constructor属性
constructor属性返回创建此对象的构造函数的引用。
实际上,一个实例被构造函数创建出来后,其本身是没有constructor属性的,其找到的constructor属性其实是这个实例的原型(通过__proto__访问)下的一个属性。
var obj = {}; |
所以我们可以想到constructor属性只能用于判断该实例的构造函数的引用,不能像instanceof那样判断该实例所有的类。
var arr = []; // 新建一个名为arr的数组 |
不过该实例的原型对象下的constructor属性是不可靠的,一旦constructor属性被修改或者原型对象被重写,就会触发异常。
var arr = []; // 新建一个名为arr的数组 |
通过上面的测试可以看出,就算constructor属性被修改了,instanceof的判断依然是可靠的。
Object.prototype.toString方法
最后介绍一种通用,而且又是最精确的方法。
// 将该方法封装成一个函数 |
实际上,这个方法显示调用了Object.toString(),返回一个表示该对象的字符串。通过判断返回的字符串(大小写不能写错)就能知道是不是我们想要的数据类型。并且这种方法可以跨<iframe>,因为该方法与实例和类的关系无关。
在IE8版本以下null和undefined的结果是"[object Object]"。// IE8
Object.prototype.toString.call(null); // "[object Object]"
Object.prototype.toString.call(undefined); // "[object Object]"
总结
介绍了四种判断数据类型的方法,最后我来做个比较总结:
typeof- 优点
- 能判断大部分的数据类型
- 运算符的速度快
- 能判断
null和undefined
- 缺点
null、对象和数组的返回结果都是"object"- 无法进一步判断对象和数组
- 优点
instanceof- 优点
- 能判断该实例所有的类,可靠
- 运算符的速度快
- 能进一步判断对象和数组
- 缺点
- 无法跨
<iframe>判断
- 无法跨
- 优点
constructor- 优点
- 实际上是判断该实例原型下的
constructor属性
- 实际上是判断该实例原型下的
- 缺点
- 如果原型下的
constructor属性被修改,结果不可靠 - 因为查找的是属性,所以比运算符的速度慢
- 如果原型下的
- 优点
Object.prototype.toString- 优点
- 实际上是显示调用Object.toString()
- 通用,所有数据类型都可以精确区分
- 能够跨
<iframe>判断
- 缺点
- 因为调用的是方法,所以速度最慢
- 优点
Object.prototype.toString虽然通用,不过性能最差,我是只有在其他方法解决不了的情况下,才会选用它。以上方法需要根据需求,灵活使用,以求代码性能的最大化。