本文系统梳理了JavaScript中判断数据类型的9种常用方法。重点解析了typeof、constructor、instanceof及Object.prototype.toString的适用场景与局限性,并补充了Array.isArray、Number.isNaN、Symbol.toStringTag及等值比较等进阶技巧,帮助开发者根据具体需求灵活选择最合适的检测手段。
前言
在JavaScript开发中,数据类型检测是面试中的高频考点。大多数开发者能够迅速列举出四种基础检测方法:typeof、constructor、instanceof 以及 Object.prototype.toString,并清楚了解它们各自的优劣。
本文不仅对上述四种方法进行了归纳,还额外补充了五种与数据类型检测相关的技巧,供读者参考使用。
typeof:检测基础数据类型和函数很好用
typeof 是许多开发者接触的第一个JavaScript检测方法,也是日常使用频率最高的工具。
它可以准确识别以下数据类型:Number、String、Boolean、Undefined、Symbol、BigInt 以及 Function。
然而,typeof 存在明显的局限性:它无法准确判断 null 的类型,会错误地返回 “object”;对于数组、Date 对象以及普通对象,它统一返回 “object”。
因此,在判断基本数据类型(排除 null)和函数类型时,typeof 是首选方案。
constructor:返回实例对象的构造函数
在学习JavaScript面向对象编程时,我们会接触到原型链和原型对象的概念。通过构造函数创建实例对象后,可以利用原型链访问 constructor 属性来追溯其构造函数,从而确定类型。
构造函数的原型对象上存在一个 constructor 属性,该属性指向构造函数本身。实例对象通过原型链访问此属性,从而确定其构造函数及对应的类型。
主要风险包括:
- null 和 undefined 没有构造函数,无法访问该属性,因此不能用于检测。
- constructor 属性可能被人为修改,导致检测结果不准确。
以下是几个示例:
console.log((1).constructor === Number) // true
console.log([1, 2, 3].constructor === Array) // true
console.log(undefined.constructor === Array) // 报错在实际编码中,通常不推荐使用 constructor 进行类型检测。
instanceof:沿着原型链去找
与 constructor 类似,instanceof 也是被“借用”来检测类型。它的主要作用是判断实例对象是否属于某个构造函数,因此可用于类型检测。
由于术业有专攻,它也存在明显的缺点:
- 无法检测基本数据类型。
- 原型链可能被修改,导致检测结果不准确。
- 只要能在原型链上找到对应的构造函数,就会返回 true,因此类型判断可能不够精确。
以下是几个示例:
console.log(1 instanceof Number) // false
console.log([] instanceof Array) // true
console.log([] instanceof Object) // true在实际应用中,instanceof 的使用频率也较低。
Object.prototype.toString:是个大拿
从名称看,它似乎用于将值转换为字符串,但实际上它是一个专门用于检测数据类型的强大方法。
它返回的字符串格式为 [object Object],例如:
console.log(toString.call('123')) // [object String]
console.log(toString.call(null)) // [object Null]
console.log(toString.call(true)) // [object Boolean]
console.log(toString.call({})) // [object Object]
console.log(toString.call([])) // [object Array]
console.log(toString.call(function(){})) // [object Function]
console.log(toString.call(new Map)) // [object Map]
console.log(toString.call(new WeakSet)) // [object WeakSet]通常我们会编写一个辅助函数,截取返回字符串的第8位到倒数第1位,然后与目标类型进行比较。
Symbol.toStringTag:自定义类型
Object.prototype.toString 之所以能针对不同数据类型返回不同的标识字符串,关键在于 Symbol.toStringTag。
Symbol.toStringTag 是一个内置符号属性,其值是一个字符串,用于表示对象的默认描述,即调用 Object.prototype.toString 时返回的内容,例如:
let obj = {}
obj[Symbol.toStringTag] = 'ABC'
console.log(Object.prototype.toString.call(obj)) // [object ABC]对于自定义对象,直接调用上述方法只会返回 [object Object]。此时,可以使用 Symbol.toStringTag 来指定一个明确的类型,例如:
class Person{
get[Symbol.toStringTag](){
return 'Person'
}
}
let person = new Person()
console.log(Object.prototype.toString.call(person)) // [object Person]Object.prototype.isPrototypeOf:和 instanceof 类似
isPrototypeOf 与 instanceof 原理相似,均基于原型链和原型对象进行判断。它用于检查一个对象是否存在于另一个对象的原型链上。
function Person() {
}
let person = new Person()
console.log(Person.prototype.isPrototypeOf(person))Array.isArray:专业检测数组三十年
起初可能误以为它是 ES6 提供的新方法,但实际上它属于 ES 5.1 规范。
从方法名即可看出,它专门用于检测数组类型,命名简洁明了。
Array.isArray([]) // trueNumber.isNaN
这个方法确实属于 ES6 标准。
我们知道,JavaScript 中有一个特殊的“数字” NaN(Not a Number),表示“不是一个数字”,但它归属于数字类型:
console.log(typeof NaN) // 'number'NaN 用于表示非数字值,它不等于任何值,包括其自身。在 ES6 之前,window 对象提供了一个全局方法 isNaN,用于判断一个值是否为 NaN:
isNaN(10) // false
isNaN('abc') // true
isNaN(NaN) // true可以发现,isNaN 对字符串的检测结果也是 NaN。但这并不严谨,因为它会对输入数据进行隐式类型转换,先转为数字再进行判断。而 NaN 的检测应仅限于数字类型,因此 ES6 提供了 Number.isNaN 方法:
Number.isNaN(NaN) // true
Number.isNaN('123') // false它能判断一个值是否严格等于 NaN。
等比较:与固定值进行比较
直接通过与特定值进行比较来判断数据类型,例如:
let value = null
console.log(value === null) // true
// 同时判断一个值是 undefined 或者 null
let value
console.log(value == null) // true总结
本文整理了 JavaScript 中常用的数据类型判断方法。其中,typeof 和 Object.prototype.toString 使用场景最为广泛。针对 null、NaN 和自定义类型等特殊数据,可以选择其他方法进行判断,以实现灵活运用。
到此这篇关于JS数据类型判断的9种方式的文章就介绍到这了,更多相关JS数据类型判断内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!