可以看到前三个都是以对象字面量创建的基本数据类型,但是却不是所属类的实例,这个就有点怪了。后面三个是引用数据类型,可以得到正确的结果。如果我们通过 new 关键字去创建基本数据类型,你会发现,这时就会输出 true,如下:
具体为什么会这样呢?我们看 MDN 的解释:
var simpleStr = "This is a simple string";
var newStr = new String("String created with constructor");
simpleStr instanceof String; // 返回 false, 非对象实例,因此返回 false
newStr instanceof String; // 返回 true
本系列的主题是 JavaScript 深入系列,每期讲解一个技术要点。如果你还不了解各系列内容,文末点击查看全部文章,点我跳转到文末。
如果觉得本系列不错,欢迎 Star,你的支持是我创作分享的最大动力。
一文搞定 JavaScript 的数据类型检测
1. typeof
对于原始数据类型,我们可以使用 typeof 操作符来判断他的数据类型:
看看控制台输出什么
可以看到,typeof 对于基本数据类型判断是没有问题的,但是遇到引用数据类型(如:Array)是不起作用的。
typeof null
在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。
曾有一个 ECMAScript 的修复提案(通过选择性加入的方式),但被拒绝了。该提案会导致 typeof null === 'null'。
2. instanceof
typeof 操作符对于原始类型的判断还差强人意,但他是没法用来区分引用数据类型的,因为所有的引用数据类型都会返回"object"。于是 JavaScript 引入了 Java 中使用的 instanceof,用来判断一个变量是否是某个对象的实例,所以对于引用类型我们使用 instanceof 来进行类型判断。
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。用法:
object instanceof constructor
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
暂且不考虑 null 和 undefined(这两个比较特殊),看看控制台输出什么。
可以看到前三个都是以对象字面量创建的基本数据类型,但是却不是所属类的实例,这个就有点怪了。后面三个是引用数据类型,可以得到正确的结果。如果我们通过 new 关键字去创建基本数据类型,你会发现,这时就会输出 true,如下:
具体为什么会这样呢?我们看 MDN 的解释:
接下再来说说为什么 null 和 undefined 为什么比较特殊,实际上按理来说,null 的所属类就是 Null,undefined 就是 Undefined,但事实并非如此:控制台输出如下结果:
浏览器压根不认识这两货,直接报错。在第一个例子你可能已经发现了,typeof null 的结果是 object,typeof undefined 的结果是 undefined
尤其是 null,其实这是 js 设计的一个败笔,早期准备更改 null 的类型为 null,由于当时已经有大量网站使用了 null,如果更改,将导致很多网站的逻辑出现漏洞问题,就没有更改过来,于是一直遗留到现在。具体为什么
typeof null = ‘object’
,我们前文已经介绍过了,作为学习者,我们只需要记住就好。3. constructor
constructor 属性返回 Object 的构造函数。
就是返回对象相对应的构造函数。从定义上来说跟 instanceof 不太一致,但效果都是一样的。
如:
(a instanceof Array)
// a 是否 Array 的实例?true or false(a.constructor == Array)
// a 实例的构造函数是否为 Array? true or false(这里依然抛开 null 和 undefined)乍一看,constructor 似乎完全可以应对基本数据类型和引用数据类型,都能检测出数据类型,事实上并不是如此,来看看为什么:
我声明了一个构造函数,并且把他的原型指向了 Array 的原型,所以这种情况下,constructor 也显得力不从心了。
看到这里,是不是觉得绝望了。没关系,终极解决办法就是第四种办法,看过 jQuery 源码的人都知道,jQuery 实际上就是采用这个方法进行数据类型检测的。
4. Object.prototype.toString.call()
可以看到,所有的数据类型,这个办法都可以判断出来。那就有人质疑了,假如我把他的原型改动一下呢?如你所愿,我们看一下:
可以看到,依然可以得到正确的结果。
总结
参考
查看全部文章
博文系列目录
交流
各系列文章汇总:https://github.com/yuanyuanbyte/Blog
我是圆圆,一名深耕于前端开发的攻城狮。