前端问题清单——怎么检测JavaScript数据类型?

465 阅读3分钟
  • 一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

问题:怎么检测JavaScript数据类型?

思路:

  • 1、JavaScript的数据类型都有什么
  • 2、随着JavaScript不断完善,出现的不同判断数据类型的方法以及一些历史包袱

JavaScript的数据类型

JavaScript的数据类型包括UndefinedNullBooleanStringSymbolNumericNumberBigInt)和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永远不会抛出错误,但是在加入了letconst后,在变量之前使用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);
}

总结

面对这么多的数据类型检测方法,没有哪个方法是最好的。对不同的数据检测类型,还是要选择适合的方法。