- 一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
问题:怎么检测JavaScript
数据类型?
思路:
- 1、
JavaScript
的数据类型都有什么 - 2、随着
JavaScript
不断完善,出现的不同判断数据类型的方法以及一些历史包袱
JavaScript
的数据类型
JavaScript的数据类型包括Undefined
、Null
、Boolean
、String
、Symbol
、Numeric
(Number
和BigInt
)和Object
方法一:typeof
运算符
检测的数据类型和返回值
类型 | 返回值 |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Symbol | "symbol" |
BigInt | "bigint" |
实现了内部[[Call]]方法的对象 | "function" |
特殊对象(document.all) | "undefined" |
其他对象 | "object" |
关于以上表格的说明
null
typeof null === 'object'
早期JavaScript
的值是由一个表示类型的标签和实际数据值组成的。对象的类型标签是0。null代表空指针(0x00),所以null的类型标签也是0,所以typeof null === 'object'
Error
在ECMA2015之前,typeof
永远不会抛出错误,但是在加入了let
和const
后,在变量之前使用typeof会抛出错误ReferenceError
方法二:instanceof
运算符
进一步区分
typeof
不能检测的其他对象
检测构造函数的prototype属性是否出现在某个实例对象的原型链上
实例对象 instanceof 构造函数
关于对象的原型
// 定义构造函数
function Test(){}
var obj = new Test()
当前情况下,obj instanceof Test
返回true
。但是在以下两种情况会改变这个表达式的返回值。
- (1)
Test.prototype
属性的值改变,改变之后的值可能不存在于obj
的原型链上,这时表达式可能是false
。 - (2)
obj
的原型链发生变化,在ES规范中,对象的原型是只读的,不能修改。但是可以借助于非标准的_proto_
伪属性改变对象的原型。
关于多个frame
或者多个window
的对象
instanceof
不能处理多个frame
或多个window
的对象
方法三:Object.prototype.toString()
每个继承Object
对象都有一个toString()
方法,如果这个方法在对象中没有被覆盖,toString()
返回"[object type]"
,type
为对象的类型。
表示对象表示为一个文本值或者对象用预期的字符串方式引用时的自动调用,所以可以使用call
或者apply
方法来改变toString
方法的执行上下文。
Object.prototype.toString.call(o) // o为待检测数据
基本上所有对象的类型都可以通过这个方法获取到
[object type]
的type
的值有:
String
,Number
,Boolean
,Undefined
,Null
,Function
,Date
,Array
,RegExp
,Error
,HTMLDocument
,HTMLBodyElement
,HTMLParagraphElement
,HTMLDivElement
等
可以处理多个frame
或者多个window
的对象类型
方法四:isXXX方法
Array.isArray
:检测数组是否是数组
Polyfill
的写法:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
Number.isNaN
:判断值是否为NaN
Polyfill
的写法:
Number.isNaN = Number.isNaN || function(value) {
return typeof value === "number" && isNaN(value);
}
总结
面对这么多的数据类型检测方法,没有哪个方法是最好的。对不同的数据检测类型,还是要选择适合的方法。